<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:series="http://unfoldingneurons.com/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Nettuts+</title> <link>http://net.tutsplus.com</link> <description>Web Development &amp; Design Tutorials</description> <lastBuildDate>Tue, 18 Jun 2013 09:18:21 +0000</lastBuildDate> <language /> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.5</generator> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/nettuts" /><feedburner:info uri="nettuts" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><image><link>http://nettuts.com</link><url>http://envato.s3.amazonaws.com/rss_images/nettuts.jpg</url><title>NETTUTS</title></image><feedburner:emailServiceId>nettuts</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><title>Advanced Python Data Structures</title><link>http://feedproxy.google.com/~r/nettuts/~3/b1jinYp469Q/</link> <comments>http://net.tutsplus.com/tutorials/advanced-python-data-structures/#comments</comments> <pubDate>Tue, 18 Jun 2013 00:20:31 +0000</pubDate> <dc:creator>Adriana Vasiu</dc:creator> <category><![CDATA[Python]]></category> <category><![CDATA[Tutorials]]></category> <category><![CDATA[data structures]]></category> <category><![CDATA[python]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32748</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32748&amp;c=1288463055' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32748&amp;c=1288463055' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;The aim of this tutorial is to show off &lt;a
href="http://www.python.org/"&gt;Python&amp;#8217;s&lt;/a&gt; data structures and the best way to use them. Depending on what you need from a data structure, whether it&amp;#8217;s fast lookup, immutability, indexing, etc, you can choose the best data structure for the job and most of the time, you will be combining data structures together to obtain a logical and easy to understand data model.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-32748"&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;Python data structures are very intuitive from a syntax point of view and they offer a large choice of operations. This tutorial tries to put together the most common and useful information about each data structure and offer a guide on when it is best to use one structure or another. You can choose different kinds of data structures depending on what the data involves, if it needs to be modified, or if it&amp;#8217;s fixed data, and even what access type you would like, such as at the beginning/end/random etc.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Lists&lt;/h2&gt;&lt;p&gt;A List represents the most versatile type of data structure in Python. It can contain items of different types and it has no rule against unicity. List indices start from zero, the elements can be sliced, concatenated, and so on. Lists also have a lot of similarities with strings, supporting the same kind of operations but unlike strings, lists are &lt;em&gt;mutable&lt;/em&gt;.&lt;/p&gt;&lt;h3&gt;How to Construct a List&lt;/h3&gt;&lt;p&gt;A list can be built using the keyword &lt;code&gt;list&lt;/code&gt; or using square brackets: &lt;code&gt;[]&lt;/code&gt;, both of which accept comma separated values. Here&amp;#8217;s an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l = ['a', 'b', 123]
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 123]
&lt;/pre&gt;&lt;h3&gt;How to Retrieve an Element From a List&lt;/h3&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l[0]
'a'
&amp;gt;&amp;gt;&amp;gt; l[10]
Traceback (most recent call last):
File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
IndexError: list index out of range
&lt;/pre&gt;&lt;p&gt;As seen above, in order to access the data within your list, you must know what index position the element is at, otherwise you get an &amp;#8220;index out of range&amp;#8221; error.&lt;/p&gt;&lt;h3&gt;How to Slice a List&lt;/h3&gt;&lt;p&gt;All slicing operations return a shallow copy of the list. The slicing indexes are optional and they work in the same way as slicing indexes for strings.&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s an example of how to slice a list:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l = ['a', 'b', 123]
&amp;gt;&amp;gt;&amp;gt; l[:]
['a', 'b', 123]
&amp;gt;&amp;gt;&amp;gt; new_l = l[1:]
&amp;gt;&amp;gt;&amp;gt; new_l
['b', 123]
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 123]
&lt;/pre&gt;&lt;p&gt;Let&amp;#8217;s take a look at some other common list operations.&lt;/p&gt;&lt;h3&gt;Inserting and Removing Elements&lt;/h3&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l = ['a', 'b', 123]
&amp;gt;&amp;gt;&amp;gt; l.append(234) #inserts an element at the end of the list
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 123, 234]
&amp;gt;&amp;gt;&amp;gt; l.insert(2, 'c') #inserts an element into the third position
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 'c', 123, 234]
&amp;gt;&amp;gt;&amp;gt; l.insert(-1, 111) #inserts an element into the second from last position of the list (negative indices start from the end of the list)
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 'c', 123, 111, 234]
&amp;gt;&amp;gt;&amp;gt; l.remove(111) #removes an element based on value
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 'c', 123, 234]
&amp;gt;&amp;gt;&amp;gt; l.remove('does not exist in the list') 
Traceback (most recent call last):
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
ValueError: list.remove(x): x not in list
&lt;/pre&gt;&lt;h3&gt;Retrieving and Looking Up Elements&lt;/h3&gt;&lt;p&gt; Lists can also be used as stacks or queues because of how easy it is to add and remove elements from the beginning or end of the list.&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; last_element = l.pop() #returns the last element, modifying the list
&amp;gt;&amp;gt;&amp;gt; last_element
234
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 'c', 123]
&amp;gt;&amp;gt;&amp;gt; third_element = l.pop(2) #returns the third element, modifying the list
&amp;gt;&amp;gt;&amp;gt; third_element
'c'
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 123]
&amp;gt;&amp;gt;&amp;gt; l.index('a') 
0
&amp;gt;&amp;gt;&amp;gt; l.index('does not exist in the list')
Traceback (most recent call last):
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
ValueError: 'does not exist in the list' is not in list
&amp;gt;&amp;gt;&amp;gt; l.count('a') #returns the number of occurrences of an element 
1
&lt;/pre&gt;&lt;h3&gt;Whole List Operations&lt;/h3&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l.extend ([1, 2]) # concatenates a list on to the existing list
&amp;gt;&amp;gt;&amp;gt; l
['a', 'b', 123, 1, 2]
&amp;gt;&amp;gt;&amp;gt; l.sort()
&amp;gt;&amp;gt;&amp;gt; l
[1, 2, 123, 'a', 'b']
&amp;gt;&amp;gt;&amp;gt; l.reverse()
&amp;gt;&amp;gt;&amp;gt; l
['b', 'a', 123, 2, 1]
&lt;/pre&gt;&lt;p&gt;As you can see, it&amp;#8217;s very easy to extend, sort, and reverse lists using the above methods.&lt;/p&gt;&lt;h3&gt;List Comprehensions&lt;/h3&gt;&lt;p&gt;A list comprehension means, constructing a list in a way that is very natural from a mathematical point of view. The code for doing this is brief and very easy to read. A simple example of when you would use list comprehensions is when you want to construct a new list based on the elements from another list. Let&amp;#8217;s have a look at how you can multiply all of the elements of a numeric list by two, in a simple one line construct:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l = [1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; new_l = [x*2 for x in l]
&amp;gt;&amp;gt;&amp;gt; new_l 
[2, 4, 6]
&lt;/pre&gt;&lt;p&gt;In the example above, the comprehension is represented by the multiplication expression that will be applied to every &lt;code&gt;x&lt;/code&gt; element in the original, &lt;code&gt;l&lt;/code&gt; list.&lt;/p&gt;&lt;h3&gt;When to Use Lists&lt;/h3&gt;&lt;p&gt; As shown in the examples above, lists are best used in the following situations:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When you need a mixed collection of data all in one place.&lt;/li&gt;&lt;li&gt;When the data needs to be ordered.&lt;/li&gt;&lt;li&gt;When your data requires the ability to be changed or extended. Remember, lists are mutable.&lt;/li&gt;&lt;li&gt;When you don&amp;#8217;t require data to be indexed by a custom value. Lists are numerically indexed and to retrieve an element, you must know its numeric position in the list.&lt;/li&gt;&lt;li&gt;When you need a stack or a queue. Lists can be easily manipulated by appending/removing elements from the beginning/end of the list.&lt;/li&gt;&lt;li&gt;When your data doesn&amp;#8217;t have to be unique. For that, you would use sets.&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;h2&gt;Sets&lt;/h2&gt;&lt;p&gt;A set is an unordered collection with no duplicate values. A set can be created by using the keyword &lt;code&gt;set&lt;/code&gt; or by using curly braces &lt;code&gt;{}&lt;/code&gt;. However, to create an empty set you can only use the &lt;code&gt;set&lt;/code&gt; construct, curly braces alone will create an empty dictionary.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; Use the &lt;code&gt;set&lt;/code&gt; keyword to create an empty set, curly brackets &lt;code&gt;{}&lt;/code&gt; will create an empty dictionary.&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;How to Construct a Set&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;set&lt;/code&gt; construct accepts one argument, a list.&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l = [1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; s = set(l)
&amp;gt;&amp;gt;&amp;gt; s
set([1, 2, 3])
&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;{}&lt;/code&gt; construct is straight forward as well:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; s = {1, 2, 3}
&amp;gt;&amp;gt;&amp;gt; s
&lt;/pre&gt;&lt;p&gt;Sets are used to eliminate duplicate values from within a list:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; l = [1, 2, 3, 3]
&amp;gt;&amp;gt;&amp;gt; s = set(l)
&amp;gt;&amp;gt;&amp;gt; s
set([1, 2, 3])
&lt;/pre&gt;&lt;p&gt;The way a &lt;code&gt;set&lt;/code&gt; detects if a clash between non-unique elements has occurred is by indexing the data in memory, creating a hash for each element. This means that all elements in a set must be hashable.&lt;/p&gt;&lt;p&gt;Here is an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; set ([1, [1,2]])
Traceback (most recent call last):
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
TypeError: unhashable type: 'list'
&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt; Note that a hashable object doesn&amp;#8217;t necessarily mean that an object has the &lt;code&gt;__hash__&lt;/code&gt; method available to it. It is important that the hash of the object doesn&amp;#8217;t change during its lifetime, which is obviously not the case with lists, sets, or dictionaries (dictionaries will be discussed later in this tutorial).&lt;/p&gt;&lt;h3&gt;Set Operations&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;set&lt;/code&gt; structure also supports mathematical operations like:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Union&lt;/li&gt;&lt;li&gt;Intersection&lt;/li&gt;&lt;li&gt;Difference&lt;/li&gt;&lt;li&gt;Symmetric Difference&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here are a few examples:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; set1 = set([1, 2, 3])
&amp;gt;&amp;gt;&amp;gt; set2 = set([3, 4, 5])
&amp;gt;&amp;gt;&amp;gt; set1 | set2 #union
set([1, 2, 3, 4, 5])
&amp;gt;&amp;gt;&amp;gt; set1 &amp;amp; set2 #intersection
set([3])
&amp;gt;&amp;gt;&amp;gt; set1 -  set2 #difference
set([1, 2])
&amp;gt;&amp;gt;&amp;gt; set1 ^ set2 #symmetric difference (elements that are in the first set and the second, but not in both)
set([1, 2, 4, 5])
&amp;gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;h3&gt;Set Comprehensions&lt;/h3&gt;&lt;p&gt;Just like lists, sets also support comprehensions. Here is an example of how to use set comprehensions to find the unique consonants within a word:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; vowels = ['a', 'e', 'i', 'o', 'u']
&amp;gt;&amp;gt;&amp;gt; {x for x in 'maintenance' if x not in vowels }
set(['c', 'm', 't', 'n'])
&lt;/pre&gt;&lt;h3&gt;Frozensets&lt;/h3&gt;&lt;p&gt;A frozenset is basically just like a regular set, except that is immutable. It is created using the keyword &lt;code&gt;frozenset&lt;/code&gt;, like this:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; frozen = frozenset([1, 2, 3])
&lt;/pre&gt;&lt;h3&gt;When to Use Sets&lt;/h3&gt;&lt;p&gt;You should choose to use a &lt;code&gt;set&lt;/code&gt; in the following situations:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When you need a unique set of data: Sets check the unicity of elements based on hashes.&lt;/li&gt;&lt;li&gt;When your data constantly changes: Sets, just like lists, are mutable.&lt;/li&gt;&lt;li&gt;When you need a collection that can be manipulated mathematically: With sets it&amp;#8217;s easy to do operations like difference, union, intersection, etc.&lt;/li&gt;&lt;li&gt;When you don&amp;#8217;t need to store nested lists, sets, or dictionaries in a data structure: Sets don&amp;#8217;t support unhashable types.&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;h2&gt;Tuples&lt;/h2&gt;&lt;blockquote
class="pullquote pqRight"&gt;&lt;p&gt; Tuples are immutable, but can hold mutable objects.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;A tuple is represented by a number of values separated by commas. Unlike lists, tuples are immutable and the output is surrounded by parentheses so that nested tuples are processed correctly. Additionally, even though tuples are immutable, they can hold mutable data if needed.&lt;br
/&gt;&lt;h3&gt;How to Construct a Tuple&lt;/h3&gt;&lt;p&gt;Constructing an empty tuple requires parentheses. Here&amp;#8217;s an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; my_empty_tuple = ()
&amp;gt;&amp;gt;&amp;gt; my_empty_tuple 
()
&lt;/pre&gt;&lt;p&gt;Constructing a tuple with one element requires a trailing comma. Example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; one_elem_tuple = 'a',
&amp;gt;&amp;gt;&amp;gt; one_elem_tuple 
('a',)
&amp;gt;&amp;gt;&amp;gt; one_elem_tuple = ('a',)
&amp;gt;&amp;gt;&amp;gt; one_elem_tuple
('a',)
&lt;/pre&gt;&lt;blockquote&gt;&lt;p&gt; If the trailing comma is not there when creating a single element tuple, regardless if you use parentheses or not, Python will just interpret the value as a literal and will not create the tuple.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Constructing a tuple with multiple elements requires a list of values separated by commas. Here&amp;#8217;s an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; s = 'a', 'b', [1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; s
('a', 'b', [1, 2, 3])
&amp;gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;p&gt;Tuples, from a performance point of view are great because of their immutability. Python will know exactly how much memory to allocate for the data to be stored.&lt;/p&gt;&lt;h3&gt;When to Use Tuples&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;When you need to store data that doesn&amp;#8217;t have to change.&lt;/li&gt;&lt;li&gt;When the performance of the application is very important. In this situation you can use tuples whenever you have fixed data collections.&lt;/li&gt;&lt;li&gt;When you want to store your data in logical immutable pairs, triples etc.&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;h2&gt;Dictionaries&lt;/h2&gt;&lt;p&gt;Dictionaries are represented by a &lt;code&gt;key:value&lt;/code&gt; pair. In other words, they are maps or associative collections. The keys, unlike lists where they are numeric, can be of any immutable type and must be unique. The values can be of any type, mutable or immutable.&lt;/p&gt;&lt;h3&gt;How to Construct a Dictionary&lt;/h3&gt;&lt;p&gt;There are several ways to construct a dictionary. The most efficient way in terms of performance is to use curly braces &lt;code&gt;{}&lt;/code&gt;:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; vowels = {1: 'a', 2: 'e', 3: 'i', 4: 'o', 5:'u'}
&amp;gt;&amp;gt;&amp;gt; vowels
{1: 'a', 2: 'e', 3: 'i', 4: 'o', 5: 'u'}
&lt;/pre&gt;&lt;p&gt;Another way to create a dictionary is by using comprehensions. By using an input collection you can create the &lt;code&gt;key:value&lt;/code&gt; pairs in one simple construct.&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; {x:x*x for x in (1, 2, 3)}
{1: 1, 2: 4, 3: 9}
&lt;/pre&gt;&lt;p&gt;You can also use the keyword &lt;code&gt;dict&lt;/code&gt; and get the same result. The &lt;code&gt;dict&lt;/code&gt; construct takes as an argument, a list of &lt;code&gt;key:value&lt;/code&gt; pairs. Here&amp;#8217;s one in action:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; dict([(1,'a'), (2,'e'), (3,'i'), (4,'o'), (5,'u')])
{1: 'a', 2: 'e', 3: 'i', 4: 'o', 5: 'u'}
&lt;/pre&gt;&lt;p&gt;If the keys are strings, you can use the following keyword expression:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; dict(a=1, e=2, i=3, o=4, u=5)
{'i': 3, 'u': 5, 'e': 2, 'a': 1, 'o': 4}
&lt;/pre&gt;&lt;p&gt;However, it does not work the other way around when the keywords are numeric:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; dict(1=a, 2=e, 3=i, 4=o, 5=u)
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1
SyntaxError: keyword can't be an expression
&lt;/pre&gt;&lt;h3&gt;Dictionary Operations&lt;/h3&gt;&lt;p&gt;Accessing data in a dictionary is very straight forward, just wrap its key name within square brackets:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; vowels = {1: 'a', 2: 'e', 3: 'i', 4: 'o', 5:'u'}
&amp;gt;&amp;gt;&amp;gt; vowels[1]
'a'
&amp;gt;&amp;gt;&amp;gt; vowels[10]
Traceback (most recent call last):
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
KeyError: 10
&amp;gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;p&gt;As seen above, a &lt;code&gt;KeyError&lt;/code&gt; occurs if the key doesn&amp;#8217;t exist in the dictionary.&lt;/p&gt;&lt;p&gt;Also, a &lt;code&gt;key:value&lt;/code&gt; pair can be deleted using the &lt;code&gt;del&lt;/code&gt; keyword, like so:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; vowels = {1: 'a', 2: 'e', 3: 'i', 4: 'o', 5:'u'}
&amp;gt;&amp;gt;&amp;gt; del(vowels[1])
&amp;gt;&amp;gt;&amp;gt; vowels
{2: 'e', 3: 'i', 4: 'o', 5: 'u'}
&amp;gt;&amp;gt;&amp;gt; del(vowels[10])
Traceback (most recent call last):
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
KeyError: 10
&amp;gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;h3&gt;Built-in Methods&lt;/h3&gt;&lt;p&gt;Dictionaries support many built-in methods, but some of the most useful ones are: &lt;code&gt;keys()&lt;/code&gt;, &lt;code&gt;values()&lt;/code&gt;, &lt;code&gt;iteritems()&lt;/code&gt;, &lt;code&gt;itervalues()&lt;/code&gt;, and &lt;code&gt;has_key()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; vowels = {1: 'a', 2: 'e', 3: 'i', 4: 'o', 5:'u'}
&amp;gt;&amp;gt;&amp;gt; vowels.keys()
[1, 2, 3, 4, 5]
&amp;gt;&amp;gt;&amp;gt; vowels.values()
['a', 'e', 'i', 'o', 'u']
&lt;/pre&gt;&lt;p&gt;The methods &lt;code&gt;iteritems()&lt;/code&gt; and &lt;code&gt;itervalues()&lt;/code&gt; return iterators, so they can be used in &lt;code&gt;for&lt;/code&gt; loops. Here&amp;#8217;s an example:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
&amp;gt;&amp;gt;&amp;gt; for k, v in vowels.iteritems():
...     print k, v
... 
1 a
2 e
3 i
4 o
5 u
&amp;gt;&amp;gt;&amp;gt; for v in vowels.itervalues():
...     print v
... 
a
e
i
o
u
&amp;gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;h3&gt;When to Use a Dictionary&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;When you need a logical association between a &lt;code&gt;key:value&lt;/code&gt; pair.&lt;/li&gt;&lt;li&gt;When you need fast lookup for your data, based on a custom key.&lt;/li&gt;&lt;li&gt;When your data is being constantly modified. Remember, dictionaries are mutable.&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;h4&gt;General Python Data Structure Usage&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Use lists if you have a collection of data that does not need random access. For random access, you need to have knowledge of the element&amp;#8217;s numeric index. Try to choose lists when you need a simple, iterable collection that is modified frequently. Lists are very useful in comprehension expressions for constructing sets or dictionaries.&lt;/li&gt;&lt;li&gt;Use a set if you need unicity for the elements and you don&amp;#8217;t need a nested dictionary or list. Also remember that a set cannot hold any unhashable data types.&lt;/li&gt;&lt;li&gt;Use tuples when your data cannot change. Many times, a tuple is used in combination with a dictionary, for example, a tuple might represent a key, because it&amp;#8217;s immutable.&lt;/li&gt;&lt;li&gt;Use frozensets if you need both unique data and immutability.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Other Tips&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Every data structure has a multitude of built in methods and capabilities. If you go through them carefully you&amp;#8217;ll learn how the data is meant to be used. For example, if you call &lt;code&gt;dir&lt;/code&gt; and pass in a set object, you will see that it holds a lot of methods that can perform mathematical operations.&lt;/li&gt;&lt;li&gt;Most of the time, your data needs to adapt to the operations that you want to perform. So if you know your object will be hashed, create an immutable structure.&lt;/li&gt;&lt;li&gt;Most data structures have multiple ways of constructing or accessing its data. If you are concerned about the performance of your application always read the documentation or read the source code of the construct implementation to find out more about its performance. For example, creating a dictionary by using &lt;code&gt;dict&lt;/code&gt; offers less performance than using the curly braces (&lt;code&gt;{}&lt;/code&gt;) syntax.&lt;/li&gt;&lt;li&gt;While debugging, many developers find it useful to learn how to identify and connect the error that they are receiving to a specific data structure. For example, you&amp;#8217;ll find that lists throw &lt;code&gt;IndexError&lt;/code&gt; and &lt;code&gt;ValueError&lt;/code&gt; and dictionaries throw &lt;code&gt;KeyError&lt;/code&gt;. This technique should help you with detecting which of your data structures is causing the error.&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=b1jinYp469Q:rhIU2IKr0ak:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=b1jinYp469Q:rhIU2IKr0ak:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=b1jinYp469Q:rhIU2IKr0ak:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=b1jinYp469Q:rhIU2IKr0ak:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=b1jinYp469Q:rhIU2IKr0ak:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=b1jinYp469Q:rhIU2IKr0ak:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=b1jinYp469Q:rhIU2IKr0ak:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=b1jinYp469Q:rhIU2IKr0ak:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/b1jinYp469Q" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/advanced-python-data-structures/feed/</wfw:commentRss> <slash:comments>8</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/advanced-python-data-structures/</feedburner:origLink></item> <item><title>Building Ribbit in Meteor</title><link>http://feedproxy.google.com/~r/nettuts/~3/LnYKSqyanxU/</link> <comments>http://net.tutsplus.com/tutorials/javascript-ajax/building-ribbit-in-meteor/#comments</comments> <pubDate>Sat, 15 Jun 2013 02:01:04 +0000</pubDate> <dc:creator>Gabriel Cirtea</dc:creator> <category><![CDATA[JavaScript & AJAX]]></category> <category><![CDATA[Tutorials]]></category> <category><![CDATA[meteor]]></category> <category><![CDATA[ribbit]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32709</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32709&amp;c=831834902' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32709&amp;c=831834902' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;This is a continuation of the Twitter clone series with building Ribbit from scratch, this time using Meteor.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-32709"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;For this tutorial, please do not expect an in depth explanation of the Meteor framework. You should already have some Meteor experience so that you&amp;#8217;ll understand some of the important concepts that will be presented. In order to get a basic understanding of Meteor I recommend Andrew Burgesses &lt;a
href="https://tutsplus.com/course/building-single-page-web-application-with-meteor-js/"&gt;course&lt;/a&gt; on Tutsplus Premium.&lt;/p&gt;&lt;p&gt;So, let&amp;#8217;s get started.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 0&lt;/span&gt;: Creating and Configuring the Meteor Application&lt;/h2&gt;&lt;p&gt;We begin by generating a new Meteor application. Open a command line prompt and navigate to the folder where you want the application to be stored. Then run:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;meteor create ribbit&lt;/pre&gt;&lt;p&gt;Meteor will create a folder named &lt;code&gt;ribbit&lt;/code&gt; containing some files and will ask you to change directory into &lt;code&gt;ribbit&lt;/code&gt; and run meteor commands in that folder.&lt;/p&gt;&lt;p&gt;If you step into the &lt;code&gt;ribbit&lt;/code&gt; folder and issue a &lt;code&gt;ls -la&lt;/code&gt; command in order to see what was generated by Meteor, you will find a hidden folder named &lt;code&gt;.meteor&lt;/code&gt; and three files named &lt;code&gt;ribbit.html&lt;/code&gt;, &lt;code&gt;ribbit.css&lt;/code&gt; and &lt;code&gt;ribbit.js&lt;/code&gt;. The &lt;code&gt;.meteor&lt;/code&gt; folder contains only one file named &lt;code&gt;packages&lt;/code&gt;. The content of the &lt;code&gt;.meteor/packages&lt;/code&gt; file informs Meteor about what smart packages are used by the application.&lt;/p&gt;&lt;p&gt;Since we will start developing Ribbit from scratch we will keep only the &lt;code&gt;.meteor&lt;/code&gt; folder and delete all the rest.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s see what packages Meteor uses by default: at the command prompt enter&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;cat .meteor/packages
&lt;/pre&gt;&lt;p&gt;The output of this command should list the autopublish, insecure, and preserve-inputs packages.&lt;/p&gt;&lt;p&gt;We will discuss the concept of publishing data from the server later, for the moment let&amp;#8217;s note that the autopublish package is used on the server side to automatically make data available to the client. Usually this packet is not used in a production environment, so we can remove it by issuing the following command:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;meteor remove autopublish
&lt;/pre&gt;&lt;p&gt;Next, the insecure package allows database writes by default, which can be dangerous, since this allows any user to do any database operations, including deleting data. We will remove this package before deploying the app and add all the necessary code to protect writing to the database.&lt;/p&gt;&lt;p&gt;And lastly, the preserve-inputs package keeps data from all of the form fields with a unique id.&lt;/p&gt;&lt;p&gt;After all of that, we should now have a folder containing just a &lt;code&gt;.meteor&lt;/code&gt; sub-folder and this should be the base of our app.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 1&lt;/span&gt;: Creating the Necessary Folder Structure&lt;/h2&gt;&lt;p&gt;There are several rules Meteor uses to serve files and data which we will not being covering in detail here (see Andrew&amp;#8217;s course for details). What is important to note, is that Meteor considers all files present in a server folder as being server code. All files in the client and public folders as being client code, which should be served to the client. And lastly, the files outside of these folders are served to both the client and the server. So let&amp;#8217;s create the following folders:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;client&lt;/strong&gt; &amp;#8211; to store all the client side code.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;server&lt;/strong&gt; &amp;#8211; to store all the server side code.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;public&lt;/strong&gt; &amp;#8211; containing all the assets such as graphic files, robots.txt&lt;br
/&gt; files, favicons etc.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Also, it&amp;#8217;s important to know that Meteor considers JavaScript and CSS files as part of the client/server code and not as assets, which should be served from the public folder.&lt;/p&gt;&lt;p&gt;So, we end up with the following folder structure:&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/folders1.jpeg" alt="Our Folder Structure" width="191" height="110" class="alignnone size-full wp-image-32717" /&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 2&lt;/span&gt;: The Static Version of the Login Page&lt;/h2&gt;&lt;p&gt;Now it&amp;#8217;s time to download the static version of the &lt;a
href="http://d2o0t5hpnwv4c1.cloudfront.net/2170_ribbit/layout.zip"&gt;Ribbit app&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;After unpacking the files, copy the &lt;code&gt;gfx&lt;/code&gt; folder into the &lt;code&gt;public&lt;/code&gt; folder of our Ribbit app.&lt;/p&gt;&lt;p&gt;Also, copy the &lt;code&gt;home.html&lt;/code&gt; and &lt;code&gt;style.less&lt;/code&gt; files into the &lt;code&gt;client&lt;/code&gt; folder of our app. Now if you would try to start the server by issuing &lt;code&gt;meteor&lt;/code&gt; from the command line, in the root of our application, you will see the server crashing and complaining about setting the &lt;code&gt;DOCTYPE&lt;/code&gt; in our file.&lt;/p&gt;&lt;p&gt;Meteor expects our HTML files to be composed from only three base elements: &lt;em&gt;the head&lt;/em&gt;, &lt;em&gt;the body&lt;/em&gt; and &lt;em&gt;the template&lt;/em&gt; tags.&lt;/p&gt;&lt;p&gt;So in order to fix the error, we should edit the &lt;code&gt;home.html&lt;/code&gt; file and remove the &lt;code&gt;DOCTYPE&lt;/code&gt; and &lt;code&gt;html&lt;/code&gt; tags, which will be added by Meteor when serving the files.&lt;/p&gt;&lt;p&gt;Now if you refresh the page, you should see its content, but it won&amp;#8217;t have any styling since the package we downloaded uses LESS for styling the page.&lt;/p&gt;&lt;p&gt;This is easy to fix by installing Meteor&amp;#8217;s LESS smart package. So issue:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;meteor add less
&lt;/pre&gt;&lt;p&gt;then restart the server and reload the page and things should look a little bit better now.&lt;/p&gt;&lt;p&gt;We still have to do some adjustments in the LESS file since not everything looks as it should. Search for all occurrences of &lt;code&gt;gfx&lt;/code&gt; in the &lt;code&gt;style.less&lt;/code&gt; file and change them by adding a trailing slash before each. This should be done in order to allow files to be loaded from the root of the project.&lt;/p&gt;&lt;p&gt;The next step is to adjust the &lt;code&gt;home.html&lt;/code&gt; and &lt;code&gt;style.less&lt;/code&gt; files to add in a login button and have everything on one line in the header. The files should look like following:&lt;/p&gt;&lt;pre class="brush: css; title: ; notranslate"&gt;// client/style.less
input {
  width: 236px;
  height: 26px;
  border: 1px solid @border-color;
  padding: 0 10px;
  outline: none;
  font-size: 17px;
  &amp;amp;amp;:focus {
    background: #FFFDF2;
  }
}

input[type=&amp;quot;submit&amp;quot;] {
  height: 26px;
  width: auto;
  border: 1px solid #7BC574;
  border-radius: 2px;
  color: white;
  font-size: 12px;
  font-weight: bold;
  padding: 0 20px;
  cursor: pointer;
  .gradient4f(0%, #8CD585, 23%, #82CD7A, 86%, #55AD4C, 100%, #4FA945);
}

header {
  background: url(/gfx/bg-header.png);
  height: 85px;
  width: 100%;
  div.wrapper {
    padding: 11px 0;
    img {
      position: relative;
      top: 10px;
      margin: 0 15px 0 0;
    }
    span {
      font-size: 18px;
      margin: 0 42px 0 0;
    }
    p {
      display: inline;
      input {
        margin: 0 0 0 14px;
        width: 180px;
        height: 28px;
      }
    }
    #btnLogOut {
      float: right;
      width: auto;
      height: 28px;
      margin: 19px 0 0 0;
    }
  }
}
&lt;/pre&gt;&lt;p&gt;And here&amp;#8217;s what the &lt;code&gt;home.html&lt;/code&gt; file should look like:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/home.html --&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;header&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;img src=&amp;quot;gfx/logo.png&amp;quot;&amp;gt;
      &amp;lt;span&amp;gt;Twitter Clone&amp;lt;/span&amp;gt;
      &amp;lt;p&amp;gt;
        &amp;lt;input name=&amp;quot;username&amp;quot; placeholder=&amp;quot;username&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
        &amp;lt;input name=&amp;quot;password&amp;quot; placeholder=&amp;quot;password&amp;quot;  type=&amp;quot;password&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;submit&amp;quot; id=&amp;quot;btnLogOut&amp;quot; value=&amp;quot;Log In&amp;quot;&amp;gt;
      &amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/header&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;img src=&amp;quot;gfx/frog.jpg&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;New to Ribbit?&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;input name=&amp;quot;email&amp;quot; placeholder=&amp;quot;email&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input name=&amp;quot;username&amp;quot; placeholder=&amp;quot;username&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input name=&amp;quot;fullname&amp;quot; placeholder=&amp;quot;fullname&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input name=&amp;quot;password&amp;quot; placeholder=&amp;quot;password&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input name=&amp;quot;password2&amp;quot; placeholder=&amp;quot;retype password&amp;quot; type=&amp;quot;password&amp;quot;&amp;gt;
          &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Create Account&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;footer&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      Ribbit - A Twitter Clone Tutorial&amp;lt;img src=&amp;quot;gfx/logo-nettuts.png&amp;quot;&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/pre&gt;&lt;p&gt;Now take a look at the page in the browser. It should look like the image below:&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/home_small.jpg" alt="Our Home page." width="600" height="297" class="alignnone size-full wp-image-32717" /&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;p&gt;Well that was pretty easy, wasn&amp;#8217;t it? But, what we&amp;#8217;ve done up to now is not what we really desired and it&amp;#8217;s definitely far from following the Meteor style of doing things. Let&amp;#8217;s fix this up!&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 3&lt;/span&gt;: Meteor-ize the Home Page&lt;/h2&gt;&lt;p&gt;Meteor constructs the HTML page that is sent to the browser based on three elements, it expects the following to be found: the head element, the body element, and the template element. Since the head and the body are already well known, special attention should be given to the template element.&lt;/p&gt;&lt;p&gt;A template is declared with &lt;code&gt;&amp;lt;template name="foo"&amp;gt;...&amp;lt;/template&amp;gt;&lt;/code&gt; and its content is rendered in the HTML content that is sent to the browser. On the other hand, in the JavaScript file, the template can be accessed using &lt;code&gt;Template.foo&lt;/code&gt;, which returns a string of HTML when called.&lt;/p&gt;&lt;p&gt;Now Meteor uses Handlebars as the template framework, but others can be used if needed, such as Jade.&lt;/p&gt;&lt;p&gt;So, let&amp;#8217;s see what should be done in order to transform the &lt;code&gt;home.html&lt;/code&gt; file into a Meteor compatible page. Let&amp;#8217;s take a look at the modified code:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/home.html --&amp;gt;
&amp;lt;head&amp;gt;

&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
  &amp;lt;header&amp;gt;
    {{&amp;gt; header}}
  &amp;lt;/header&amp;gt;
  {{&amp;gt; content}}
  &amp;lt;footer&amp;gt;
    {{&amp;gt; footer}}
  &amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;template name=&amp;quot;header&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
    &amp;lt;img src=&amp;quot;gfx/logo.png&amp;quot;&amp;gt;
    &amp;lt;span&amp;gt;Twitter Clone&amp;lt;/span&amp;gt;
    &amp;lt;p&amp;gt;
      &amp;lt;input id=&amp;quot;username&amp;quot; name=&amp;quot;username&amp;quot; placeholder=&amp;quot;username&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
      &amp;lt;input id=&amp;quot;password&amp;quot; name=&amp;quot;password&amp;quot; placeholder=&amp;quot;password&amp;quot;  type=&amp;quot;password&amp;quot;&amp;gt;
      &amp;lt;input id=&amp;quot;btnLogOut&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Log In&amp;quot;&amp;gt;
    &amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;template name=&amp;quot;content&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;img src=&amp;quot;gfx/frog.jpg&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;New to Ribbit?&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;input id=&amp;quot;email&amp;quot; name=&amp;quot;email&amp;quot; placeholder=&amp;quot;email&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;newusername&amp;quot; name=&amp;quot;username&amp;quot; placeholder=&amp;quot;username&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;fullname&amp;quot; name=&amp;quot;fullname&amp;quot; placeholder=&amp;quot;fullname&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;newpassword&amp;quot; name=&amp;quot;password&amp;quot; placeholder=&amp;quot;password&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;password2&amp;quot; name=&amp;quot;password2&amp;quot; placeholder=&amp;quot;retype password&amp;quot; type=&amp;quot;password&amp;quot;&amp;gt;
          &amp;lt;input id= &amp;quot;btnCreateAccount&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Create Account&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;template name=&amp;quot;footer&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
    Ribbit - A Twitter Clone Tutorial&amp;lt;img src=&amp;quot;gfx/logo-nettuts.png&amp;quot;&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;As you can see, we start with an empty head element. Since Meteor loads all the necessary files for us, we can use the head element to establish the page&amp;#8217;s title, but for the moment, it&amp;#8217;s blank.&lt;/p&gt;&lt;p&gt;Inside the body element, we render three templates: the header template, which we place in the header tag, the content template, which is placed right after the header, and finally the footer template, inside a footer tag.&lt;/p&gt;&lt;p&gt;What I&amp;#8217;ve done for these templates, was to simply copy the old code and place it into the appropriate template. So what was in the header tag, is now in the header template and so on.&lt;/p&gt;&lt;p&gt;I&amp;#8217;ve also added some ids to the edit boxes and the buttons, so that later, I&amp;#8217;m able to access these from the JavaScript code.&lt;/p&gt;&lt;p&gt;And that&amp;#8217;s it. Now our page is finished and works well with the Meteor framework.&lt;/p&gt;&lt;p&gt;The next step will be to create the buddies page which should be displayed when a user logs into the system. We also need to allow the user to sign up and log in to our application.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 4&lt;/span&gt;: Log Into the Buddies Page&lt;/h2&gt;&lt;p&gt;If we follow the same steps from in the previous section, to transform the &lt;code&gt;buddies.html&lt;/code&gt; page into a Meteor one, we end with the following code:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/buddies.html --&amp;gt;
&amp;lt;head&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;header&amp;gt;
    {{&amp;gt; header}}
  &amp;lt;/header&amp;gt;
  {{&amp;gt; content}}
  &amp;lt;footer&amp;gt;
    {{&amp;gt; footer}}
  &amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;template name=&amp;quot;header&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
    &amp;lt;img src=&amp;quot;gfx/logo.png&amp;quot;&amp;gt;
    &amp;lt;span&amp;gt;Twitter Clone&amp;lt;/span&amp;gt;
    &amp;lt;p&amp;gt;
      &amp;lt;input type=&amp;quot;submit&amp;quot; id=&amp;quot;btnLogOut&amp;quot; value=&amp;quot;Log Out&amp;quot;&amp;gt;
    &amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;template name=&amp;quot;content&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;div id=&amp;quot;createRibbit&amp;quot; class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Create a Ribbit&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;textarea name=&amp;quot;text&amp;quot; class=&amp;quot;ribbitText&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
          &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Ribbit!&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div id=&amp;quot;ribbits&amp;quot; class=&amp;quot;panel left&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Your Ribbit Profile&amp;lt;/h1&amp;gt;
        &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
          &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user1.png&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;Frogger&amp;lt;/span&amp;gt; @username
          &amp;lt;p&amp;gt;
            567 Ribbits&amp;lt;span class=&amp;quot;spacing&amp;quot;&amp;gt;45 Followers&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;spacing&amp;quot;&amp;gt;32 Following&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;http://net.tutsplus.com/tutorials/php/ ...&amp;lt;/a&amp;gt;
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class=&amp;quot;panel left&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Your Ribbit Buddies&amp;lt;/h1&amp;gt;
        &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
          &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user2.png&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;Kermit&amp;lt;/span&amp;gt; @username &amp;lt;span class=&amp;quot;time&amp;quot;&amp;gt;15m&amp;lt;/span&amp;gt;
          &amp;lt;p&amp;gt;
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;http://net.tutsplus.com/tutorials/php/ ...&amp;lt;/a&amp;gt;
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;template name=&amp;quot;footer&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
    Ribbit - A Twitter Clone Tutorial&amp;lt;img src=&amp;quot;gfx/logo-nettuts.png&amp;quot;&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;As you can see, I took out the long list of ribbits, but other than that, there&amp;#8217;s nothing else too impressive about the above code.&lt;/p&gt;&lt;p&gt;However, there are two problems with it:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;If you try viewing it in the browser, you will find it&amp;#8217;s being displayed twice. There are two reasons for this: Meteor sends files to the browser in alphabetical order, so &lt;code&gt;buddies.html&lt;/code&gt; is sent first. We also have a lot of duplication in the code, even the name of the templates are duplicated. So when Meteor wants to display the content template, it displays the first defined one, which is the one in the &lt;code&gt;buddies.html&lt;/code&gt; file.&lt;/li&gt;&lt;li&gt;The second problem is also code duplication, which needs to be fixed.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The issues above can be resolved by doing the following: we will create an &lt;code&gt;index.html&lt;/code&gt; file containing only the code that will trigger the needed templates: one for the header, one for the footer, one for the home page, and one for the buddies page.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s take a look of each of them:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/index.html --&amp;gt;
&amp;lt;head&amp;gt;

&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
  &amp;lt;header&amp;gt;
    {{&amp;gt; header}}
  &amp;lt;/header&amp;gt;
  {{#if currentUser}}
    {{&amp;gt; buddiescontent}}
  {{else}}
    {{&amp;gt; homecontent}}
  {{/if}}
  &amp;lt;footer&amp;gt;
    {{&amp;gt; footer}}
  &amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/pre&gt;&lt;p&gt;This is the main file in which all of the templates are loaded. A very interesting thing can be found when the content template is displayed. We check with a Handlebars &lt;code&gt;if&lt;/code&gt; clause whether a user is logged in or not. The Meteor &lt;code&gt;currentUser&lt;/code&gt; variable contains the logged in user&amp;#8217;s data, if a user is logged in (so we display the buddies template) and is null if no user is logged in (so we display the home template).&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/header.html --&amp;gt;
&amp;lt;template name=&amp;quot;header&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
    &amp;lt;img src=&amp;quot;gfx/logo.png&amp;quot;&amp;gt;
    &amp;lt;span&amp;gt;Twitter Clone&amp;lt;/span&amp;gt;
    {{#if currentUser}}
      &amp;lt;nav&amp;gt;
        &amp;lt;a id=&amp;quot;buddies&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Your Buddies&amp;lt;/a&amp;gt;
        &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Public Ribbits&amp;lt;/a&amp;gt;
        &amp;lt;a id='profiles' href=&amp;quot;#&amp;quot;&amp;gt;Profiles&amp;lt;/a&amp;gt;
      &amp;lt;/nav&amp;gt;
      &amp;lt;input type=&amp;quot;submit&amp;quot; id=&amp;quot;btnLogOut&amp;quot; value=&amp;quot;Log Out&amp;quot; /&amp;gt;
    {{else}}
      &amp;lt;p&amp;gt;
        &amp;lt;input id=&amp;quot;username&amp;quot; name=&amp;quot;username&amp;quot; placeholder=&amp;quot;username&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
        &amp;lt;input id=&amp;quot;password&amp;quot; name=&amp;quot;password&amp;quot; placeholder=&amp;quot;password&amp;quot;  type=&amp;quot;password&amp;quot;&amp;gt;
        &amp;lt;input id=&amp;quot;btnLogOut&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Log In&amp;quot;&amp;gt;
      &amp;lt;/p&amp;gt;
    {{/if}}
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;Here we render the header for our pages, and as above, if a user is logged in, we display a navigation bar, otherwise we display a log in form.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/footer.html --&amp;gt;
&amp;lt;template name=&amp;quot;footer&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
    Ribbit - A Twitter Clone Tutorial&amp;lt;img src=&amp;quot;gfx/logo-nettuts.png&amp;quot;&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;Then we create the footer template, which only renders the content in the footer.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/home.html --&amp;gt;
&amp;lt;template name=&amp;quot;homecontent&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;img src=&amp;quot;gfx/frog.jpg&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;New to Ribbit?&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;input id=&amp;quot;email&amp;quot; name=&amp;quot;email&amp;quot; placeholder=&amp;quot;email&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;newusername&amp;quot; name=&amp;quot;username&amp;quot; placeholder=&amp;quot;username&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;fullname&amp;quot; name=&amp;quot;fullname&amp;quot; placeholder=&amp;quot;fullname&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;newpassword&amp;quot; name=&amp;quot;password&amp;quot; placeholder=&amp;quot;password&amp;quot; type=&amp;quot;password&amp;quot;&amp;gt;
          &amp;lt;input id=&amp;quot;password2&amp;quot; name=&amp;quot;password2&amp;quot; placeholder=&amp;quot;retype password&amp;quot; type=&amp;quot;password&amp;quot;&amp;gt;
          &amp;lt;input id= &amp;quot;btnCreateAccount&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Create Account&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;Now we&amp;#8217;ve already saw this template before, it just contains a form to allow the users to register for the application.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/buddies.html --&amp;gt;
&amp;lt;template name=&amp;quot;buddiescontent&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;div id=&amp;quot;createRibbit&amp;quot; class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Create a Ribbit&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;textarea name=&amp;quot;text&amp;quot; class=&amp;quot;ribbitText&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
          &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Ribbit!&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div id=&amp;quot;ribbits&amp;quot; class=&amp;quot;panel left&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Your Ribbit Profile&amp;lt;/h1&amp;gt;
        &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
          &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user1.png&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;Frogger&amp;lt;/span&amp;gt; @username
          &amp;lt;p&amp;gt;
            567 Ribbits&amp;lt;span class=&amp;quot;spacing&amp;quot;&amp;gt;45 Followers&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;spacing&amp;quot;&amp;gt;32 Following&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;http://net.tutsplus.com/tutorials/php/ ...&amp;lt;/a&amp;gt;
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class=&amp;quot;panel left&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Your Ribbit Buddies&amp;lt;/h1&amp;gt;
        &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
          &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user2.png&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;Kermit&amp;lt;/span&amp;gt; @username &amp;lt;span class=&amp;quot;time&amp;quot;&amp;gt;15m&amp;lt;/span&amp;gt;
          &amp;lt;p&amp;gt;
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;http://net.tutsplus.com/tutorials/php/ ...&amp;lt;/a&amp;gt;
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;And then the last template, containing information about the current user, that user&amp;#8217;s ribbits, and the people the current user is following.&lt;/p&gt;&lt;p&gt;Up until now, we have two pages of our application which can be displayed, but both are static and we can display only one at a time. So next, let&amp;#8217;s add some JavaScript to our application to make it more dynamic.&lt;/p&gt;&lt;h3&gt;Registering and Logging In&lt;/h3&gt;&lt;p&gt;Meteor gives us several smart packages to handle the process of registering and logging in to an application. For our Ribbit app, we will use following packages: accounts-base for basic support for accounting and accounts-password for getting password support for accounting. To install these packages, run the following commands:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;meteor add accounts-base
meteor add accounts-password
&lt;/pre&gt;&lt;p&gt;Now, let&amp;#8217;s create a &lt;code&gt;client.js&lt;/code&gt; file in the &lt;code&gt;client&lt;/code&gt; folder to hold our client side code. For the home page, we need to handle events for clicking on the &lt;code&gt;Log In&lt;/code&gt; button and &lt;code&gt;Create Account&lt;/code&gt; button.&lt;/p&gt;&lt;p&gt;Events in Meteor are associated with a specific template, so in order to handle clicking on the &lt;code&gt;Log In&lt;/code&gt; button we will add an event handler for the header template. To handle the click event for the &lt;code&gt;Create Account&lt;/code&gt; button, we have to add an event handler associated with the homecontent template.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s take a look at the code:&lt;/p&gt;&lt;h5&gt;Clicking on the Log In Button&lt;/h5&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/client.js
// handling click event on the Log In button
Template.header.events({
  'click #btnLogOut': function (event, template) {
    if (Meteor.userId()) {
      Meteor.logout();
    } else {
      var userName     = template.find('#username').value,
        userPassword = template.find('#password').value;
      Meteor.loginWithPassword(userName, userPassword, function (error) {
        if (error) {
          console.log(error);
        }
      });
    }
  }
});
&lt;/pre&gt;&lt;p&gt;On the first line, we attach an events object to the header template. Then we handle the click event on the button with an id of &lt;code&gt;btnLogOut&lt;/code&gt; (which we&amp;#8217;ve created in our HTML template). Then if a user is logged in, simply log the user out. If &lt;code&gt;Meteor.userId&lt;/code&gt; returns null, that means no user is logged in, so we perform a log in with the supplied username and password. Also, notice the values that are inserted in the edit boxes: the template object has a find function which takes as a parameter, the ID of the edit box for which we want to get the value of. If there is an error during logging in, we just display it in the console. For now, this is a temporary approach since we will implement displaying information to the user a little bit later.&lt;/p&gt;&lt;h5&gt;Clicking on the Create Account Button&lt;/h5&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/client.js
// hnadling click event on the Create Accounts button
Template.homecontent.events({
  'click #btnCreateAccount': function (event, template) {
    var userEmail = template.find('#email').value,
      userName  = template.find('#newusername').value,
      password  = template.find('#newpassword').value,
      password2 = template.find('#password2').value,
      name      = template.find('#fullname').value;

    Accounts.createUser({
      username: userName,
      email:    userEmail,
      password: password,
      profile: {
        name: name
      }
    }, function (error) {
      if (error) {
        console.log(&amp;quot;Cannot create user&amp;quot;);
      }
    });
  }
});
&lt;/pre&gt;&lt;p&gt;Just like before, we attach an events object to the &lt;code&gt;homecontent&lt;/code&gt; template, then we get the values submitted by the user from the form fields. To create an account we simply use the &lt;code&gt;Accounts.createUser&lt;/code&gt; function, which takes as a parameter an object with the username, password, email and profile components. In case of an error while adding the user, the error is displayed in the console.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 5&lt;/span&gt;: Making the Buddies Page Dynamic&lt;/h2&gt;&lt;p&gt;The next step in developing our application is to make the buddies page dynamic. At the moment, everything displayed on our page is statically taken from the template files. We want to take the information from a database and also to allow the user to create ribbits and store them in a database on the server side.&lt;/p&gt;&lt;h3&gt;Changing the Your Ribbit Profile Section&lt;/h3&gt;&lt;p&gt;This section displays the full name of the user, their username, the number of ribbits the current logged in user has, the number of followers and following people, and the last ribbit posted by the user.&lt;/p&gt;&lt;p&gt;We will store the code for this part in a &lt;code&gt;main.js&lt;/code&gt; file. Note that Meteor loads files with the word &lt;code&gt;main&lt;/code&gt; in their name, after the page is loaded.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s see how to display them in the template:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/buddies.html --&amp;gt;
...
  &amp;lt;div id=&amp;quot;ribbits&amp;quot; class=&amp;quot;panel left&amp;quot;&amp;gt;
&amp;lt;h1&amp;gt;Your Ribbit Profile&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
&amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user1.png&amp;quot;&amp;gt;
&amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;{{fullName}}&amp;lt;/span&amp;gt; @{{userName}}
&amp;lt;p&amp;gt;
{{noOfRibbits}}&amp;lt;span class=&amp;quot;spacing&amp;quot;&amp;gt;45 Followers&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;spacing&amp;quot;&amp;gt;32 Following&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;
{{lastRibbit}}
&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
...
&lt;/pre&gt;&lt;p&gt;What we want to do in this template is to use Handlebars&amp;#8217; variables for the items we&amp;#8217;d like to pull from the database. The &lt;code&gt;fullname&lt;/code&gt; and the &lt;code&gt;username&lt;/code&gt; are taken from the users collection and the &lt;code&gt;noOfRibbits&lt;/code&gt; and &lt;code&gt;lastRibbit&lt;/code&gt; should be taken from the ribbit collection.&lt;/p&gt;&lt;p&gt;The above variables are returned to the template by the following JavaScript code in the &lt;code&gt;main.js&lt;/code&gt; file:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/main.js
Ribbits = new Meteor.Collection('ribbits');

Template.buddiescontent.helpers({
  fullName: function () {
    return Meteor.user().profile.name;
  },

  userName: function () {
    return Meteor.user().username;
  },

  noOfRibbits: function () {
    var ribbits = Ribbits.find({user_id: Meteor.userId()}),
      retVal;
    if (ribbits.count() === 1) {
      retVal = &amp;quot;1 Ribbit&amp;quot;;
    } else {
      retVal = ribbits.count() + &amp;quot; Ribbits&amp;quot;;
    }
    return retVal;
  },

  lastRibbit: function () {
    var lastRibbit = Ribbits.findOne({user_id: Meteor.userId()}, {sort: {created_at: -1}}),
      retVal;

    if (lastRibbit) {
      retVal = lastRibbit.ribbit;
    } else {
      retVal = 'This user has no Ribbits';
    }

    return retVal;
  }
});
&lt;/pre&gt;&lt;p&gt;Two of Meteor&amp;#8217;s principles state that access to the database is done using the same API on both the server and the client and on the client side there is a model simulation, which should look like a zero-latency connection to the database (latency compensation). These principles can be seen in the above code, on line one. We create a Ribbits instance of a Meteor collection, which is the client side database. Since on the server side, we don&amp;#8217;t have a ribbits collection, the one defined in our code will be empty.&lt;/p&gt;&lt;p&gt;Next, a helpers function is defined, which takes as a parameter, an object with a function for each Handlebars variable in the template. As you can see, for each one, the appropriate data is returned.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;fullName&lt;/code&gt; and &lt;code&gt;userName&lt;/code&gt; are both taken from the users database profile object.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;noOfRibbits&lt;/code&gt; and the &lt;code&gt;lastRibbit&lt;/code&gt; should be taken from the Ribbits collection. Since this is empty at the moment, we expect the functions above to return zero as the number of ribbits and the message, &amp;#8216;This user has no Ribbits&amp;#8217;, instead of the last ribbit.&lt;/p&gt;&lt;h3&gt;Changing the Your Ribbit Buddies Section&lt;/h3&gt;&lt;p&gt;Let&amp;#8217;s take a look at the code. First the template:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/buddies.html --&amp;gt;
&amp;lt;div class=&amp;quot;panel left&amp;quot;&amp;gt;
&amp;lt;h1&amp;gt;Your Ribbit Buddies&amp;lt;/h1&amp;gt;
{{#each ribbits}}
&amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
  &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user2.png&amp;quot;&amp;gt;
  &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;{{buddyFullName}}&amp;lt;/span&amp;gt; @{{buddyUserName}} &amp;lt;span class=&amp;quot;time&amp;quot;&amp;gt;15m&amp;lt;/span&amp;gt;
  &amp;lt;p&amp;gt;
  {{ribbit}}
  &amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
{{/each}}
&lt;/pre&gt;&lt;p&gt;The new thing here is that we use Handlebars&amp;#8217; &lt;code&gt;each&lt;/code&gt; to loop through all the ribbits returned from the JavaScript function. The rest is pretty similar to the code inside of the profile section.&lt;/p&gt;&lt;p&gt;Now for the JavaScript code:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/main.js
...
buddyFullName: function () {
  Ribbits.find().forEach(function (ribbit) {
    var theUser = Meteor.users.findOne({_id: ribbit.user_id});

    return theUser.profile.name;
  });
},

buddyUserName: function () {
  Ribbits.find().forEach(function (ribbit) {
    var theUser = Meteor.users.findOne({_id: ribbit.user_id});

    return theUser.username;
  });
},

ribbits: function () {
  return Ribbits.find();
}
&lt;/pre&gt;&lt;p&gt;In this area we want to display all of the ribbits belonging to the current logged in user and all of the users which are followed by the current logged in user. We will implement on the server, a mechanism for returning only the ribbits to the client, that fulfill the above condition. In the client, the Ribbits collection is scanned and for each, a user with the same id as the one stored in the ribbit collection is searched. Then the full name and the username are returned to the template. As for the ribbits, since we already have the ones we are interested in, they can just be returned entirely to the template.&lt;/p&gt;&lt;h3&gt;Creating a Ribbit&lt;/h3&gt;&lt;p&gt;When adding a ribbit, there are two main tasks that should be completed:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;First we should insert a record into the ribbits collection.&lt;/li&gt;&lt;li&gt;Next, update the buddies page with the following information: number of&lt;br
/&gt; ribbits, the last ribbit in the &amp;#8220;Your Ribbit Profile&amp;#8221; section, and the last&lt;br
/&gt; ribbit, which could have been posted by any user, along with its author and the time elapsed since it was posted.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It&amp;#8217;s now time to write a little bit of server code. Let&amp;#8217;s start with the following:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// server/server.js
Ribbits = new Meteor.Collection('ribbits');
Meteor.publish('ribbits', function () {
  return Ribbits.find({});
});
&lt;/pre&gt;&lt;p&gt;For the above code, we create a Meteor collection instance for the ribbits collection and we publish all the ribbits data to the client.&lt;/p&gt;&lt;p&gt;Now for the client side code:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/client.js
Ribbits = new Meteor.Collection('ribbits');
Meteor.subscribe('ribbits');

...

// handling the click event on the Ribbit button
Template.buddiescontent.events({
  'click #createTheRibbit': function (event, template) {
    var ribbitContent= template.find('.ribbitText').value;

    Ribbits.insert({
      user_id: Meteor.user()._id,
      ribbit: ribbitContent,
      created_at: new Date()
    });
    template.find('.ribbitText').value = &amp;quot;&amp;quot;;
  }
});
&lt;/pre&gt;&lt;p&gt;Just like the server side, the client also holds a Ribbits instance of the ribbits collection, in order to support the concept of &amp;#8220;Data everywhere&amp;#8221;. Additionally, it must also subscribe to the data published by the server in order to make sure that modifications done on one instance of the application are replicated everywhere.&lt;/p&gt;&lt;p&gt;After that, the click event for the Ribbit! button is handled like so: the data inserted into the text field is read and inserted into the ribbits collection. Afterwards, the content of the text field is set to an empty string.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/main.js
ribbits: function () {
  return Ribbits.find({}, {sort: {created_at: -1}});
},

buddyFullName: function (ribbitUserId) {
  var theUser = Meteor.users.findOne({_id: ribbitUserId});
  return theUser.profile.name;
},

buddyUserName: function (ribbitUserId) {
  var theUser = Meteor.users.findOne({_id: ribbitUserId});
  return theUser.username;
},

elapsedTime: function (text) {
  var currentDate = new Date(),
    ribbitDate,
    minutes_elapsed,
    hours_elapsed,
    days_elapsed,
    retVal,
    record = Ribbits.findOne({ribbit: text});

  ribbitDate = new Date(record.created_at);
  minutes_elapsed = (currentDate - ribbitDate) / 60000;
  if (minutes_elapsed &amp;gt; 60) {
    hours_elapsed = minutes_elapsed / 60;
    if (hours_elapsed &amp;gt; 24) {
      days_elapsed = hours_elapsed / 24;
      retVal = parseInt(days_elapsed, 10) + &amp;quot;d&amp;quot;;
    } else {
      retVal = parseInt(hours_elapsed, 10) + &amp;quot;h&amp;quot;;
    }
  } else {
    retVal = parseInt(minutes_elapsed, 10) + &amp;quot;m&amp;quot;;
  }
  return retVal;
}
&lt;/pre&gt;&lt;p&gt;Now the above code injects dynamic data into the Handlebars&amp;#8217; template variables. Allow me to explain:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The &lt;code&gt;ribbits&lt;/code&gt; value is replaced by a collection instance with all of the values stored in the database, in the reverse order of creation.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;buddyFullName&lt;/code&gt; is returned by searching the users collection for a user with the same id as the current ribbit&amp;#8217;s user. Notice that the ribbitUserId is a parameter received by the function from the template.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;buddyUserName&lt;/code&gt; is obtained in a similar manner as the buddyFullName.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;elapsedTime&lt;/code&gt; is calculated based on the current time and the time of when a ribbit was originally created.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The &lt;code&gt;buddies&lt;/code&gt; template now looks like the following:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/buddies.html --&amp;gt;
&amp;lt;div class=&amp;quot;panel left&amp;quot;&amp;gt;
  &amp;lt;h1&amp;gt;Your Ribbit Buddies&amp;lt;/h1&amp;gt;
  {{#each ribbits}}
  &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
    &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user2.png&amp;quot;&amp;gt;
    &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;{{buddyFullName user_id}}&amp;lt;/span&amp;gt; @{{buddyUserName user_id}} &amp;lt;span class=&amp;quot;time&amp;quot;&amp;gt;{{elapsedTime ribbit}}&amp;lt;/span&amp;gt;
    &amp;lt;p&amp;gt;
    {{ribbit}}
    &amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
  {{/each}}
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;What is interesting to notice here, is that the &lt;code&gt;buddyFullName&lt;/code&gt; is followed by the &lt;code&gt;user_id&lt;/code&gt; variable taken from the ribbits collection. This is the parameter from the function we described above.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 6&lt;/span&gt;: Creating the Public Ribbits Page&lt;/h2&gt;&lt;p&gt;This task shouldn&amp;#8217;t be a show stopper since we already did something similar with the buddies page. What needs to be done here is to take the &lt;code&gt;public.html&lt;/code&gt; file from the downloaded assets and turn it into a template. We&amp;#8217;ll then hook the data that we want displayed on the page, to some JavaScript functions, that will take that data from the database and return it to the template.&lt;/p&gt;&lt;p&gt;First, let&amp;#8217;s see the template file:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/public.html --&amp;gt;
&amp;lt;template name=&amp;quot;public&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Create a Ribbit&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;textarea name=&amp;quot;text&amp;quot; class=&amp;quot;ribbitText&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
          &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Ribbit!&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;&amp;lt;!-- panel right --&amp;gt;
      &amp;lt;div id=&amp;quot;ribbits&amp;quot; class=&amp;quot;panel left&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Public Ribbits&amp;lt;/h1&amp;gt;
        {{#each ribbits}}
          &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
            &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;gfx/user2.png&amp;quot;&amp;gt;
            &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;{{publicUserFull user_id}}&amp;lt;/span&amp;gt; @{{publicUserName user_id}} &amp;lt;span class=&amp;quot;time&amp;quot;&amp;gt;{{elapsedTime ribbit}}&amp;lt;/span&amp;gt;
            &amp;lt;p&amp;gt;
              {{ribbit}}
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;&amp;lt;!-- ribbitWrapper --&amp;gt;
        {{/each}}
      &amp;lt;/div&amp;gt;&amp;lt;!-- panel left --&amp;gt;
    &amp;lt;/div&amp;gt;&amp;lt;!-- wrapper --&amp;gt;
  &amp;lt;/div&amp;gt;&amp;lt;!-- content --&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;Nothing spectacular here: in the Public Ribbits section there is the &lt;code&gt;publicUserFull&lt;/code&gt; and &lt;code&gt;publicUserName&lt;/code&gt; displayed as well as the ribbit &lt;code&gt;user_id&lt;/code&gt; is sent to the function connected to these.&lt;/p&gt;&lt;p&gt;The JavaScript code looks like following:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/client.js
...
Template.public.helpers({
  ribbits: function () {
    return Ribbits.find({}, {sort: {created_at: -1}});
  },

  publicUserFull: function (currentRibbitId) {
    var theUser = Meteor.users.findOne({_id: currentRibbitId});

    return theUser.profile.name;
  },

  publicUserName: function (currentRibbitId) {
    var theUser = Meteor.users.findOne({_id: currentRibbitId});

    return theUser.username;
  },

  elapsedTime: function (text) {
    var currentDate = new Date(),
      ribbitDate,
      minutes_elapsed,
      hours_elapsed,
      days_elapsed,
      retVal,
      record = Ribbits.findOne({ribbit: text});

    ribbitDate = new Date(record.created_at);
    minutes_elapsed = (currentDate - ribbitDate) / 60000;
    if (minutes_elapsed &amp;gt; 60) {
      hours_elapsed = minutes_elapsed / 60;
      if (hours_elapsed &amp;gt; 24) {
        days_elapsed = hours_elapsed / 24;
        retVal = parseInt(days_elapsed, 10) + &amp;quot;d&amp;quot;;
      } else {
        retVal = parseInt(hours_elapsed, 10) + &amp;quot;h&amp;quot;;
      }
    } else {
      retVal = parseInt(minutes_elapsed, 10) + &amp;quot;m&amp;quot;;
    }
    return retVal;
  }
});
...
&lt;/pre&gt;&lt;p&gt;Notice that all of the functions in this code fragment are similar to the ones defined in the buddies part of the file. You should see that we have massive code repetition going on here, which is not so good. But for the moment, let&amp;#8217;s leave it as is, in order to see that it works and we&amp;#8217;ll figure out how we can refactor this in a later step.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 7&lt;/span&gt;: Display the Public Ribbits Page&lt;/h2&gt;&lt;p&gt;So we have a functional public Ribbits page, but there&amp;#8217;s no way to display it. This is what we&amp;#8217;ll fix in this step.&lt;/p&gt;&lt;p&gt;In order to perform this task, we will use Meteor&amp;#8217;s reactive data concept. We already saw this in action on the buddies page; when a new ribbit is added, it is automatically displayed on the page.&lt;/p&gt;&lt;p&gt;What we want to achieve is that whenever a user clicks on the Public Ribbits link in the header, to change from the current page that is being displayed, to the Public Ribbits page. So we need a &lt;code&gt;currentPage&lt;/code&gt; variable, that we can change periodically, so it points to the desired page.&lt;/p&gt;&lt;p&gt;We will use the Meteor&amp;#8217;s Session global object, which contains an arbitrary set of key-value pairs. We will store a string in a &lt;code&gt;currentPage&lt;/code&gt; variable, which points to the name of the page that we want to display. Then when clicking on a link, we change the &lt;code&gt;currentPage&lt;/code&gt; variable as appropriate to display the new page.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s get started on the code. First, the main template file, index.html:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!-- client/index.html --&amp;gt;
&amp;lt;head&amp;gt;

&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
  &amp;lt;header&amp;gt;
    {{&amp;gt; header}}
  &amp;lt;/header&amp;gt;
  {{&amp;gt; content}}
  &amp;lt;footer&amp;gt;
    {{&amp;gt; footer}}
  &amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;template name=&amp;quot;content&amp;quot;&amp;gt;
  {{#if currentUser}}
    {{#if currentPage &amp;quot;buddies&amp;quot;}}
      {{&amp;gt; buddiescontent}}
    {{/if}}

    {{#if currentPage &amp;quot;public&amp;quot;}}
      {{&amp;gt; public}}
    {{/if}}

    {{#if currentPage &amp;quot;profile&amp;quot;}}
      {{&amp;gt; profile}}
    {{/if}}
  {{else}}
    {{&amp;gt; homecontent}}
  {{/if}}
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;The changes in this file are small. A new template named &lt;code&gt;content&lt;/code&gt; was added and in this template the value of the &lt;code&gt;currentPage&lt;/code&gt; variable is checked and the appropriate sub-template is rendered.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s see how this reflects in the JavaScript code:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/main.js
Template.content.helpers({
  currentPage: function (type) {
    var thePage = Session.get(&amp;quot;currentPage&amp;quot;);
    return thePage === type;
  }
});
&lt;/pre&gt;&lt;p&gt;A helper for the &lt;code&gt;content&lt;/code&gt; template was added, containing a &lt;code&gt;currentPage&lt;/code&gt; function, which returns a boolean by checking the parameter sent to this function against the value of the &lt;code&gt;currentPage&lt;/code&gt;, stored in the Meteor&amp;#8217;s Session. The function returns &lt;code&gt;true&lt;/code&gt; if they are the same or &lt;code&gt;false&lt;/code&gt; if they are not. This way its value can be checked in the template to decide which sub-template is rendered.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/client.js
Session.set(&amp;quot;currentPage&amp;quot;, &amp;quot;buddies&amp;quot;);
&lt;/pre&gt;&lt;p&gt;Now for the &lt;code&gt;client.js&lt;/code&gt; file, the value of &lt;code&gt;currentPage&lt;/code&gt; is initialized at the beginning of the application by storing it in &lt;code&gt;buddies&lt;/code&gt;, so by default, if a user is logged in, the buddies page is displayed.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// client/client.js
...
'click #public': function (event, template) {
  Session.set(&amp;quot;currentPage&amp;quot;, &amp;quot;public&amp;quot;);
},

'click #buddies': function (event, template) {
  Session.set(&amp;quot;currentPage&amp;quot;, &amp;quot;buddies&amp;quot;);
},
...
&lt;/pre&gt;&lt;p&gt;Then, the header events object is updated by adding two click handlers, one for the &lt;code&gt;Public Ribbits&lt;/code&gt; link and one for the &lt;code&gt;Your Buddies&lt;/code&gt; link, so that the user can navigate to these pages:&lt;/p&gt;&lt;p&gt;As you can see in this function, the only thing we do is set the Session value of &lt;code&gt;currentPage&lt;/code&gt; to the desired value.&lt;/p&gt;&lt;p&gt;And that&amp;#8217;s it. Now it&amp;#8217;s possible to switch between buddies and the public page using the links in the page&amp;#8217;s header.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;&lt;span&gt;Step 8&lt;/span&gt;: Creating the Profiles Page&lt;/h2&gt;&lt;p&gt;As you might have noticed, there is a pattern we&amp;#8217;ve followed throughout this tutorial while creating each new page: we started with the implementation of the page template, then we added the necessary JavaScript code for making the page dynamic. Lastly, we add in some event handlers for the actions that the user may take on the page. Let&amp;#8217;s follow this same pattern now for creating the &lt;code&gt;profiles&lt;/code&gt; page.&lt;/p&gt;&lt;h3&gt;The Profile Template&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;profile&lt;/code&gt; template code should look like this:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;template name=&amp;quot;profile&amp;quot;&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;panel right&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Search for profiles&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;input name=&amp;quot;query&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;
          &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Search!&amp;quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div id=&amp;quot;ribbits&amp;quot; class=&amp;quot;panel left&amp;quot;&amp;gt;
        &amp;lt;h1&amp;gt;Public Profiles&amp;lt;/h1&amp;gt;
        {{#each users}}
          &amp;lt;div class=&amp;quot;ribbitWrapper&amp;quot;&amp;gt;
            &amp;lt;img class=&amp;quot;avatar&amp;quot; src=&amp;quot;{{gravatarLink _id}}&amp;quot;&amp;gt;
            &amp;lt;span class=&amp;quot;name&amp;quot;&amp;gt;{{profile.name}}&amp;lt;/span&amp;gt; @{{username}} &amp;lt;span class=&amp;quot;time&amp;quot;&amp;gt;{{noOfFollowers _id}}&amp;lt;a href=&amp;quot;#&amp;quot; id='{{_id}}' class='follow'&amp;gt;{{followText _id}}&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;p id='last-ribbit'&amp;gt;
              {{lastRibbit _id}}
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;
        {{/each}}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/pre&gt;&lt;p&gt;For this template, our page is split into two panels: the right panel allows searching for a specific user profile and on the left panel we have a list of registered users. Also on the left panel, the logged in user has the possibility to follow or unfollow another user by clicking the follow/unfollow link.&lt;/p&gt;&lt;p&gt;Since the left panel&amp;#8217;s code looks more interesting, let&amp;#8217;s start analyzing it first: after the header part, we iterate over the Meteor users collection using a Handlebars &lt;code&gt;#each&lt;/code&gt; construction.&lt;/p&gt;&lt;p&gt;For each user we display the following information:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The user&amp;#8217;s gravatar (retrieved just as we did on the buddies page).&lt;/li&gt;&lt;li&gt;The user&amp;#8217;s name, taken from the mongoDb database.&lt;/li&gt;&lt;li&gt;The user&amp;#8217;s username.&lt;/li&gt;&lt;li&gt;The user&amp;#8217;s number of follows.&lt;/li&gt;&lt;li&gt;The follow/unfollow link.&lt;/li&gt;&lt;li&gt;The user&amp;#8217;s last ribbit.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As for the right panel, this code contains a form that allows the user to search for a specific profile.&lt;/p&gt;&lt;p&gt;Now, let&amp;#8217;s move on to the second step of our pattern by adding in the JavaScript.&lt;/p&gt;&lt;h3&gt;Getting the Profile Data&lt;/h3&gt;&lt;p&gt;The first thing the template needs is the &lt;code&gt;users&lt;/code&gt; collection. Let&amp;#8217;s take a look at the code that returns this collection:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;users: function () {
  if (Session.get('searchedName') !== undefined) {
    return Meteor.users.find({
      $and: [
        {_id: {$ne: Meteor.userId()}},
        {username: Session.get('searchedName')}
      ]
    });
  } else {
    return Meteor.users.find({_id: {$ne: Meteor.userId()}});
  }
},
&lt;/pre&gt;&lt;p&gt;The above code takes care of the profile search functionality for our app. In short, the collection returned to the template is filtered to contain only the searched user and if no search was performed, all of the users are returned, except the current logged in user.&lt;/p&gt;&lt;p&gt;Let me explain this in more detail: When a search for a specific user profile is performed, as we will see later, we set a profile variable named &lt;code&gt;searchedName&lt;/code&gt;, which hold the name that the user is searching for. We then filter the users collection using the &lt;code&gt;$and&lt;/code&gt; Mongo construction to meet the following criteria: It should only return users that are not the current logged in user and inside of &lt;code&gt;username&lt;/code&gt; we&amp;#8217;ll store the &lt;code&gt;searchedName&lt;/code&gt;. I have to admit, that I am simplifying things a bit here, since I could implement a &lt;code&gt;like&lt;/code&gt; clause instead to return all users with a username similar to the &lt;code&gt;searchedName&lt;/code&gt;. But since this is not a Mongo tutorial, I&amp;#8217;m going to leave this as an additional exercise for you to try out on your own.&lt;/p&gt;&lt;p&gt;By default, this should display all of the users except the current&lt;br
/&gt; logged in user, which is done in the else clause.&lt;/p&gt;&lt;p&gt;As for obtaining the gravatar image, the code is similar to what we used in the buddies template, so I won&amp;#8217;t describe it again here.&lt;/p&gt;&lt;p&gt;The same also applies for the name, username, and noOfFollowers.&lt;/p&gt;&lt;p&gt;Now for the followText part, we are going to do things a little differently. The behavior we intend to have here is to display the &amp;#8216;follow&amp;#8217; text if the current logged in user is not already following the displayed user. Otherwise, we want to allow the user to stop following the user by displaying the text &amp;#8216;unfollow&amp;#8217;.&lt;/p&gt;&lt;p&gt;The code looks like following:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;followText: function (userId) {
  var followee = Follows.findOne({
    $and: [
      {followee_id: Meteor.userId()},
      {user_id: userId}
    ]
  });
  if (followee) {
    return 'unfollow';
  } else {
    return 'follow';
  }
},
&lt;/pre&gt;&lt;p&gt;This function receives the &lt;code&gt;userId&lt;/code&gt; parameter from the template and performs a search in the Follows table for a user that has a &lt;code&gt;followee_id&lt;/code&gt; which matches the current user&amp;#8217;s id and which also has a &lt;code&gt;user_id&lt;/code&gt;, which matches the id of the user who was clicked on. If this criteria is met, that means the user is being followed by the current logged in user, so return the &amp;#8216;unfollow&amp;#8217; string, otherwise return the &amp;#8216;follow&amp;#8217; string.&lt;/p&gt;&lt;h3&gt;Actions on the Profile Page&lt;/h3&gt;&lt;p&gt;There are really only two actions users can make on the Profile page: clicking on the Search! button, to search for other user profiles. And the second action is to follow or unfollow another user by clicking the appropriate link.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s tackle them one by one:&lt;/p&gt;&lt;h4&gt;Searching a User&lt;/h4&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;'click input[type=&amp;quot;submit&amp;quot;]': function(event, template) {
  var searchedUser = template.find('input[type=&amp;quot;text&amp;quot;]').value;
  if (searchedUser !== &amp;quot;&amp;quot;) {
    Session.set('searchedName', searchedUser);
  } else {
    Session.set('searchedName', undefined);
  }
  Template.profile();
}
&lt;/pre&gt;&lt;p&gt;When the user clicks on our Search! button (the input field with a type of submit), we read the name entered into the text field and set a session variable named &lt;code&gt;searchedName&lt;/code&gt; to hold this value. We&amp;#8217;ve already saw from the previous step how this variable is used to perform a search in the database and return a subset of the users collection containing only users with that username.&lt;/p&gt;&lt;h4&gt;Following a User&lt;/h4&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;'click .follow': function(event, template) {
  var isFollowed, theClickedUserId = event.currentTarget.id,
    theFollowees = Follows.find({user_id: theClickedUserId});

  theFollowees.forEach(function (theFollowee) {
    if (theFollowee.followee_id === Meteor.userId()) {
      isFollowed = true;
    } else {
      isFollowed = false;
    }
  });

  if (!isFollowed) {
    Follows.insert({
      user_id: theClickedUserId,
      followee_id: Meteor.userId()
    });
  } else {
    Follows.remove({
     $and: [
       {user_id: theClickedUserId},
       {followee_id: Meteor.user()._id}
      ]
    });
  }
},
&lt;/pre&gt;&lt;p&gt;We start off with the &lt;code&gt;theClickedUserId&lt;/code&gt; variable, which will store the id of the user who was clicked on. Then we search in the Follows collection for all of the users with that id and store the result in the &lt;code&gt;theFollowees&lt;/code&gt; variable.&lt;/p&gt;&lt;p&gt;The next step is to loop through the &lt;code&gt;theFollowees&lt;/code&gt; collection and check if the current followee has the same &lt;code&gt;followee_id&lt;/code&gt; as the current logged in user&amp;#8217;s id. If so, the logged in user is following the clicked on user.&lt;/p&gt;&lt;p&gt;Finally, if the user is not followed, just add it to the Follows collection, which will result in following that user, otherwise, remove it from the Follows collection, to unfollow that user.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;This concludes the Profile page implementation and also this tutorial. I hope you will find it interesting and discover that working with Meteor indeed changes the way JavaScript applications are being developed. If you have any questions feel free to ask away in the comments below!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=LnYKSqyanxU:pUpVyW45P2U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=LnYKSqyanxU:pUpVyW45P2U:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=LnYKSqyanxU:pUpVyW45P2U:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=LnYKSqyanxU:pUpVyW45P2U:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=LnYKSqyanxU:pUpVyW45P2U:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=LnYKSqyanxU:pUpVyW45P2U:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=LnYKSqyanxU:pUpVyW45P2U:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=LnYKSqyanxU:pUpVyW45P2U:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/LnYKSqyanxU" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/building-ribbit-in-meteor/feed/</wfw:commentRss> <slash:comments>7</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/building-ribbit-in-meteor/</feedburner:origLink></item> <item><title>Tuts+ Jobs is now free!</title><link>http://feedproxy.google.com/~r/nettuts/~3/GVdOO744w4E/</link> <comments>http://net.tutsplus.com/articles/news/tuts-jobs-is-now-free/#comments</comments> <pubDate>Fri, 14 Jun 2013 15:12:08 +0000</pubDate> <dc:creator>Joel Bankhead</dc:creator> <category><![CDATA[News]]></category> <category><![CDATA[jobs]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32576</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32576&amp;c=802901483' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32576&amp;c=802901483' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;&lt;strong&gt;Our awesome &lt;a
href="https://jobs.tutsplus.com/"&gt;new job board&lt;/a&gt; is now free and full of enticing opportunities!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a
href="https://jobs.tutsplus.com/"&gt;Tuts+ Jobs&lt;/a&gt; is a job board for full time, part time and casual employment opportunities for web and creative professionals. A brand new site to go alongside the &lt;a
href="http://tutsplus.com/"&gt;Tuts+ Educational Network&lt;/a&gt; and the &lt;a
href="http://themeforest.net/"&gt;Envato Marketplaces&lt;/a&gt;, all run by &lt;a
href="http://envato.com/"&gt;Envato&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;There&amp;#8217;s no need to sign up to apply for jobs, and it&amp;#8217;s now free to post a job &amp;#8211; &lt;a
href="https://jobs.tutsplus.com/"&gt;try it now&lt;/a&gt;!&lt;br
/&gt; &lt;span
id="more-32576"&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Earn and Learn&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Envato is committed to helping people earn and learn online.&lt;/strong&gt; We provide a wealth of educational material through Tuts+ and Tuts+ Premium, alongside the Envato Marketplaces to help you benefit from the creative skills you learn.&lt;/p&gt;&lt;p&gt;&lt;a
href="https://jobs.tutsplus.com/"&gt;Tuts+ Jobs&lt;/a&gt; furthers this vision perfectly. With Tuts+ you can learn the skills you need to become a creative professional, and with Tuts+ Jobs you can find an amazing job that uses those skills. Our goal here is to take the hassle out of finding a job, so we&amp;#8217;ve made the process as simple as can be!&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;a
href="http://net.tutsplus.com/articles/news/tuts-jobs-is-now-free/attachment/600/" rel="attachment wp-att-32578"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/600.png" alt="600" width="600" height="189" class="alignnone size-full wp-image-32578" /&gt;&lt;/a&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;hr
/&gt;&lt;h2&gt;Finding a Job&lt;/h2&gt;&lt;p&gt;With &lt;a
href="https://jobs.tutsplus.com/"&gt;Tuts+ Jobs&lt;/a&gt; we&amp;#8217;re committed to making every step of the job-finding process more intuitive, simpler and more efficient. We don&amp;#8217;t want to stand between you and a great opportunity.&lt;/p&gt;&lt;p&gt;It&amp;#8217;s totally free to sign up and start applying for jobs, and if nothing matches your initial search you can receive notifications when jobs come up that match your criteria. We will have full time, part time and casual listings from all around the world. Check the listing to find out where the job is based, as some jobs may offer remote opportunities.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;a
href="http://net.tutsplus.com/articles/news/tuts-jobs-is-now-free/attachment/2-2/" rel="attachment wp-att-32590"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/2.jpg" alt="2" width="600" height="353" class="alignnone size-full wp-image-32590" /&gt;&lt;/a&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;hr
/&gt;&lt;h2&gt;Posting a Job&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Posting a job is now free!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;If you have a position that you need to fill, or a great part/full-time opportunity, then Tuts+ Jobs is the best way to find a talented and creative individual to do that job. Each 30-day listing is completely free, regardless of the type of job you&amp;#8217;re posting.&lt;/p&gt;&lt;p&gt;Your job listing will be promoted across the entire Tuts+ network. With exposure to our ten million visitors over the course of 30 days, it&amp;#8217;s a brilliant way to reach exactly the type of audience you&amp;#8217;re looking for.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Sign Up, Explore, and Subscribe&lt;/h2&gt;&lt;p&gt;There are lots of great opportunities already on Tuts+ Jobs, and we&amp;#8217;ll be posting even more exciting job positions over the next few weeks, so now is the best time to head over to the site and &lt;a
href="https://jobs.tutsplus.com/"&gt;subscribe to a job search&lt;/a&gt; that interests you. That way you&amp;#8217;ll be the first to know when any new listings show up that match your skill set and requirements.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a
href="https://jobs.tutsplus.com"&gt;Check out Tuts+ Jobs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=GVdOO744w4E:dxdoUm1XWWg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=GVdOO744w4E:dxdoUm1XWWg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=GVdOO744w4E:dxdoUm1XWWg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=GVdOO744w4E:dxdoUm1XWWg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=GVdOO744w4E:dxdoUm1XWWg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=GVdOO744w4E:dxdoUm1XWWg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=GVdOO744w4E:dxdoUm1XWWg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=GVdOO744w4E:dxdoUm1XWWg:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/GVdOO744w4E" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/articles/news/tuts-jobs-is-now-free/feed/</wfw:commentRss> <slash:comments>5</slash:comments> <feedburner:origLink>http://net.tutsplus.com/articles/news/tuts-jobs-is-now-free/</feedburner:origLink></item> <item><title>Combining Laravel 4 and Backbone</title><link>http://feedproxy.google.com/~r/nettuts/~3/sp8nPXhAUws/</link> <comments>http://net.tutsplus.com/tutorials/javascript-ajax/combining-laravel-4-and-backbone/#comments</comments> <pubDate>Fri, 14 Jun 2013 01:33:16 +0000</pubDate> <dc:creator>Conar Welsh</dc:creator> <category><![CDATA[JavaScript & AJAX]]></category> <category><![CDATA[PHP]]></category> <category><![CDATA[backbone.js]]></category> <category><![CDATA[laravel]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=31745</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=31745&amp;c=1529330245' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=31745&amp;c=1529330245' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;For this tutorial, we&amp;#8217;re going to be building a single page app using &lt;a
href="http://laravel.com/"&gt;Laravel 4&lt;/a&gt; and &lt;a
href="http://backbonejs.org/"&gt;Backbone.js&lt;/a&gt;. Both frameworks make it very easy to use a different templating engine other than their respective default, so we&amp;#8217;re going to use Mustache, which is an engine that is common to both. By using the same templating language on both sides of our application, we&amp;#8217;ll be able to share our views betweem them, saving us from having to repeat our work multiple times.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-31745"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Our Backbone app will be powered by a Laravel 4 JSON API which we&amp;#8217;ll develop together. Laravel 4 comes with some new features that make the development of this API very easy. I&amp;#8217;ll show you a few tricks along the way to allow you to stay a bit more organized.&lt;/p&gt;&lt;p&gt;All of our dependencies will be managed by Package Managers, there will be no manual downloading or updating of libraries for this application! In addition, I&amp;#8217;ll be showing you how to leverage a little extra power from some of our dependencies.&lt;/p&gt;&lt;p&gt;For this project we&amp;#8217;ll be using:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a
href="http://four.laravel.com"&gt;Laravel 4&lt;/a&gt;: A great PHP framework.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/bobthecow/mustache.php"&gt;Mustache.php&lt;/a&gt;: The PHP rendering engine for &lt;a
href="http://mustache.github.io/"&gt;Mustache&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/janl/mustache.js/"&gt;Mustache.js&lt;/a&gt;: The JavaScript rendering engine for &lt;a
href="http://mustache.github.io/"&gt;Mustache&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/JeffreyWay/Laravel-4-Generators"&gt;Jeffrey Way&amp;#39;s Generators for Laravel 4&lt;/a&gt;: We can improve our workflow by generating some boilerplate code for us using these generators.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://twitter.github.io/bootstrap/"&gt;Twitter Bootstrap&lt;/a&gt;: A front-end library to aid in our styling.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/sebastianbergmann/phpunit/"&gt;PHPUnit&lt;/a&gt;: A PHP testing suite.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/padraic/mockery"&gt;Mockery&lt;/a&gt;: Used for mocking PHP Objects while testing.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://backbonejs.org/"&gt;Backbone.js&lt;/a&gt;: A Javascript MVC for our single page app.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://underscorejs.org/"&gt;Underscore.js&lt;/a&gt;: A dependency of Backbone, and a great little toolkit of functions.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To complete this tutorial, you&amp;#8217;ll need the following items installed:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a
href="http://getcomposer.org/"&gt;Composer&lt;/a&gt;: You can download this from the homepage, I recommend the global install instructions located &lt;a
href="http://getcomposer.org/doc/00-intro.md#globally"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://nodejs.org/"&gt;Node + NPM&lt;/a&gt;: the installer on the homepage will install both items.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://lesscss.org/"&gt;LESS Compiler&lt;/a&gt;: If you&amp;#8217;re on a Mac, I recommend CodeKit. However, regardless of your operating system, or if you do not feel like paying for CodeKit, you can just install the LESS Compiler for Node.js by typing &lt;code&gt;npm install -g less&lt;/code&gt; at the command prompt.&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;h2&gt;Part 1: The Base Architecture&lt;/h2&gt;&lt;p&gt;First things first, we need to get our application setup before we can begin adding our business logic to it. We&amp;#8217;ll do a basic setup of Laravel 4 and get all of our dependencies installed using our Package Managers.&lt;/p&gt;&lt;h3&gt;Git&lt;/h3&gt;&lt;p&gt;Let&amp;#39;s start by creating a git repository to work in. For your reference, this entire repo will be made publicly available at &lt;a
href="https://github.com/conarwelsh/nettuts-laravel4-and-backbone"&gt;https://github.com/conarwelsh/nettuts-laravel4-and-backbone&lt;/a&gt;.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;mkdir project &amp;amp;&amp;amp; cd project
git init
&lt;/pre&gt;&lt;h3&gt;Laravel 4 Installation&lt;/h3&gt;&lt;p&gt;Laravel 4 uses Composer to install all of its dependencies, but first we&amp;#8217;ll need an application structure to install into. The &amp;#8220;develop&amp;#8221; branch on &lt;a
href="https://github.com/laravel/laravel"&gt;Laravel&amp;#39;s Github repository&lt;/a&gt; is the home for this application structure. However, at the time of writing this article, Laravel 4 was still in beta, so I needed to be prepared for this structure to change at any time. By adding Laravel as a remote repository, we can pull in these changes whenever we need to. In fact, while something is in beta-mode, it&amp;#8217;s a good practice to run these commands after each &lt;code&gt;composer update&lt;/code&gt;. However, Laravel 4 is now the newest, stable version.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;git remote add laravel https://github.com/laravel/laravel
git fetch laravel
git merge laravel/develop
git add . &amp;amp;&amp;amp; git commit -am &amp;quot;commit the laravel application structure&amp;quot;
&lt;/pre&gt;&lt;p&gt;So we have the application structure, but all of the library files that Laravel needs are not yet installed. You&amp;#8217;ll notice at the root of our application there&amp;#8217;s a file called &lt;code&gt;composer.json&lt;/code&gt;. This is the file that will keep track of all the dependencies that our Laravel application requires. Before we tell Composer to download and install them, let&amp;#39;s first add a few more dependencies that we&amp;#8217;re going to need. We&amp;#8217;ll be adding:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a
href="https://packagist.org/packages/way/generators"&gt;Jeffrey Way&amp;#39;s Generators&lt;/a&gt;: Some very useful commands to greatly improve our workflow by automatically generating file stubs for us.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://packagist.org/packages/conarwelsh/mustache-l4"&gt;Laravel 4 Mustache&lt;/a&gt;: This will allow us to seamlessly use Mustache.php in our Laravel project, just as we would Blade.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://packagist.org/packages/twitter/bootstrap"&gt;Twitter Bootstrap&lt;/a&gt;: We&amp;#8217;ll use the LESS files from this project to speed up our front-end development.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://packagist.org/packages/phpunit/phpunit"&gt;PHPUnit&lt;/a&gt;: We&amp;#8217;ll be doing some TDD for our JSON API, PHPUnit will be our testing engine.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://packagist.org/packages/mockery/mockery"&gt;Mockery&lt;/a&gt;: Mockery will help us &amp;quot;mock&amp;quot; objects during our testing.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;PHPUnit and Mockery are only required in our development environment, so we&amp;#8217;ll specify that in our composer.json file.&lt;/p&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;composer.json&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;{
  &amp;quot;require&amp;quot;: {
    &amp;quot;laravel/framework&amp;quot;: &amp;quot;4.0.*&amp;quot;,
    &amp;quot;way/generators&amp;quot;: &amp;quot;dev-master&amp;quot;,
    &amp;quot;twitter/bootstrap&amp;quot;: &amp;quot;dev-master&amp;quot;,
    &amp;quot;conarwelsh/mustache-l4&amp;quot;: &amp;quot;dev-master&amp;quot;
  },
  &amp;quot;require-dev&amp;quot;: {
    &amp;quot;phpunit/phpunit&amp;quot;: &amp;quot;3.7.*&amp;quot;,
    &amp;quot;mockery/mockery&amp;quot;: &amp;quot;0.7.*&amp;quot;
  },
  &amp;quot;autoload&amp;quot;: {
    &amp;quot;classmap&amp;quot;: [
      &amp;quot;app/commands&amp;quot;,
      &amp;quot;app/controllers&amp;quot;,
      &amp;quot;app/models&amp;quot;,
      &amp;quot;app/database/migrations&amp;quot;,
      &amp;quot;app/database/seeds&amp;quot;,
      &amp;quot;app/tests/TestCase.php&amp;quot;
    ]
  },
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;post-update-cmd&amp;quot;: &amp;quot;php artisan optimize&amp;quot;
  },
  &amp;quot;minimum-stability&amp;quot;: &amp;quot;dev&amp;quot;
}
&lt;/pre&gt;&lt;p&gt;Now we just need to tell Composer to do all of our leg work! Below, notice the &lt;code&gt;--dev&lt;/code&gt; switch, we&amp;#8217;re telling composer that we&amp;#8217;re in our development environment and that it should also install all of our dependencies listed in &lt;code&gt;&amp;quot;require-dev&amp;quot;&lt;/code&gt;.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;composer install --dev
&lt;/pre&gt;&lt;p&gt;After that finishes installing, we&amp;#8217;ll need to inform Laravel of a few of our dependencies. Laravel uses &amp;quot;service providers&amp;quot; for this purpose. These service providers basically just tell Laravel how their code is going to interact with the application and to run any necessary setup procedures. Open up &lt;code&gt;app/config/app.php&lt;/code&gt; and add the following two items to the &amp;quot;&lt;code&gt;providers&lt;/code&gt;&amp;quot; array. Not all packages require this, only those that will enhance or change the functionality of Laravel.&lt;/p&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;app/config/app.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;...

'Way\Generators\GeneratorsServiceProvider',
'Conarwelsh\MustacheL4\MustacheL4ServiceProvider',

...
&lt;/pre&gt;&lt;p&gt;Lastly, we just need to do some generic application tweaks to complete our Laravel installation. Let&amp;#39;s open up &lt;code&gt;bootstrap/start.php&lt;/code&gt; and tell Laravel our machine name so that it can determine what environment it&amp;#8217;s in.&lt;/p&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;bootstrap/start.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;/*
|--------------------------------------------------------------------------
| Detect The Application Environment
|--------------------------------------------------------------------------
|
| Laravel takes a dead simple approach to your application environments
| so you can just specify a machine name or HTTP host that matches a
| given environment, then we will automatically detect it for you.
|
*/

$env = $app-&amp;gt;detectEnvironment(array(

  'local' =&amp;gt; array('your-machine-name'),

));
&lt;/pre&gt;&lt;p&gt;Replace &amp;quot;your-machine-name&amp;quot; with whatever the hostname for your machine is. If you are unsure of what your exact machine name is, you can just type &lt;code&gt;hostname&lt;/code&gt; at the command prompt (on Mac or Linux), whatever it prints out is the value that belongs in this setting.&lt;/p&gt;&lt;p&gt;We want our views to be able to be served to our client from a web request. Currently, our views are stored outside of our &lt;code&gt;public&lt;/code&gt; folder, which would mean that they are &lt;em&gt;not&lt;/em&gt; publicly accessible. Luckily, Laravel makes it very easy to move or add other view folders. Open up &lt;code&gt;app/config/view.php&lt;/code&gt; and change the &lt;code&gt;paths&lt;/code&gt; setting to point to our public folder. This setting works like the PHP native include path, it will check in each folder until it finds a matching view file, so feel free to add several here:&lt;/p&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;app/config/view.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;'paths' =&amp;gt; array(__DIR__.'/../../public/views'),
&lt;/pre&gt;&lt;p&gt;Next you will need to configure your database. Open up &lt;code&gt;app/config/database.php&lt;/code&gt; and add in your database settings.&lt;/p&gt;&lt;p&gt;Note: It is recommended to use &lt;code&gt;127.0.0.1&lt;/code&gt; instead of &lt;code&gt;localhost&lt;/code&gt;. You get a bit of a performance boost on most systems, and with some system configurations, &lt;code&gt;localhost&lt;/code&gt; will not even connect properly.&lt;/p&gt;&lt;p&gt;Finally, you just need to make sure that your storage folder is writable.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;chmod -R 755 app/storage
&lt;/pre&gt;&lt;p&gt;Laravel is now installed, with all of its dependencies, as well as our own dependencies. Now let&amp;#39;s setup our Backbone installation!&lt;/p&gt;&lt;p&gt;Just like our &lt;code&gt;composer.json&lt;/code&gt; installed all of our server-side dependencies, we&amp;#8217;ll create a &lt;code&gt;package.json&lt;/code&gt; in our &lt;em&gt;public folder&lt;/em&gt; to install all of our client-side dependencies.&lt;/p&gt;&lt;p&gt;For our client-side dependencies we&amp;#8217;ll use:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a
href="https://npmjs.org/package/underscore"&gt;Underscore.js&lt;/a&gt;: This is a dependency of Backbone.js, and a handy toolbelt of functions.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://npmjs.org/package/backbone"&gt;Backbone.js&lt;/a&gt;: This is our client-side MVC that we&amp;#8217;ll use to build out our application.&lt;/li&gt;&lt;li&gt;&lt;a
href="https://npmjs.org/package/mustache"&gt;Mustache.js&lt;/a&gt;: The Javascript version of our templating library, by using the same templating language both on the client and the server, we can share views, as opposed to duplicating logic.&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;public/package.json&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;nettuts-laravel4-and-backbone&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;0.0.1&amp;quot;,
  &amp;quot;private&amp;quot;: true,
  &amp;quot;dependencies&amp;quot;: {
    &amp;quot;underscore&amp;quot;: &amp;quot;*&amp;quot;,
    &amp;quot;backbone&amp;quot;: &amp;quot;*&amp;quot;,
    &amp;quot;mustache&amp;quot;: &amp;quot;*&amp;quot;
  }
}
&lt;/pre&gt;&lt;p&gt;Now just switch into your public folder, and run &lt;code&gt;npm install&lt;/code&gt;. After that completes, lets switch back to our application root so we&amp;#8217;re prepared for the rest of our commands.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;cd public
npm install
cd ..
&lt;/pre&gt;&lt;p&gt;Package managers save us from a ton of work, should you want to update any of these libraries, all you have to do is run &lt;code&gt;npm update&lt;/code&gt; or &lt;code&gt;composer update&lt;/code&gt;. Also, should you want to lock any of these libraries in at a specific version, all you have to do is specify the version number, and the package manager will handle the rest.&lt;/p&gt;&lt;p&gt;To wrap up our setup process we&amp;#8217;ll just add in all of the basic project files and folders that we&amp;#8217;ll need, and then test it out to ensure it all works as expected.&lt;/p&gt;&lt;p&gt;We&amp;#8217;ll need to add the following folders:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;public/views&lt;/li&gt;&lt;li&gt;public/views/layouts&lt;/li&gt;&lt;li&gt;public/js&lt;/li&gt;&lt;li&gt;public/css&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And the following files:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;public/css/styles.less&lt;/li&gt;&lt;li&gt;public/js/app.js&lt;/li&gt;&lt;li&gt;public/views/app.mustache&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To accomplish this, we can use a one-liner:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;mkdir public/views public/views/layouts public/js public/css &amp;amp;&amp;amp; touch public/css/styles.less public/js/app.js public/views/app.mustache
&lt;/pre&gt;&lt;p&gt;Twitter Bootstrap also has two JavaScript dependencies that we&amp;#8217;ll need, so let&amp;#39;s just copy them from the vendor folder into our public folder. They are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;html5shiv.js&lt;/strong&gt;: allows us to use HTML5 elements without fear of older browsers not supporting them&lt;/li&gt;&lt;li&gt;&lt;strong&gt;bootstrap.min.js&lt;/strong&gt;: the supporting JavaScript libraries for Twitter Bootstrap&lt;/li&gt;&lt;/ul&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;cp vendor/twitter/bootstrap/docs/assets/js/html5shiv.js public/js/html5shiv.js
cp vendor/twitter/bootstrap/docs/assets/js/bootstrap.min.js public/js/bootstrap.min.js
&lt;/pre&gt;&lt;p&gt;For our layout file, the Twitter Bootstrap also provides us with some nice starter templates to work with, so let&amp;#39;s copy one into our layouts folder for a head start:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;cp vendor/twitter/bootstrap/docs/examples/starter-template.html public/views/layouts/application.blade.php
&lt;/pre&gt;&lt;blockquote&gt;&lt;p&gt;Notice that I am using a blade extension here, this could just as easily be a mustache template, but I wanted to show you how easy it is to mix the templating engines. Since our layout will be rendered on page load, and will not need to be re-rendered by the client, we are safe to use PHP here exclusively. If for some reason you find yourself needing to render this file on the client-side, you would want to switch this file to use the Mustache templating engine instead.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Now that we have all of our basic files in place, let&amp;#39;s add some starter content that we can use to test that everything is working as we would expect. I&amp;#8217;m providing you with some basic stubs to get you started.&lt;/p&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;public/css/styles.less&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We&amp;#8217;ll just import the Twitter Bootstrap files from the vendor directory as opposed to copying them. This allows us to update Twitter Bootstrap with nothing but a &lt;code&gt;composer update&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;We declare our variables at the end of the file, the LESS compiler will figure out the value of all of its variables before parsing the LESS into CSS. This means that by re-defining a Twitter Bootstrap variable at the end of the file, the value will actually change for all of the files included, allowing us to do simple overrides without modifying the Twitter Bootstrap core files.&lt;/p&gt;&lt;pre class="brush: css; title: ; notranslate"&gt;/**
 * Import Twitter Bootstrap Base File
 ******************************************************************************************
 */
@import &amp;quot;../../vendor/twitter/bootstrap/less/bootstrap&amp;quot;;
/**
 * Define App Styles
 * Do this before the responsive include, so that it can override properly as needed.
 ******************************************************************************************
 */
body {
  padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}

/* this will set the position of our alerts */
#notifications {
  width: 300px;
  position: fixed;
  top: 50px;
  left: 50%;
  margin-left: -150px;
  text-align: center;
}

/**
 * Import Bootstrap's Responsive Overrides
 * now we allow bootstrap to set the overrides for a responsive layout
 ******************************************************************************************
 */
@import &amp;quot;../../vendor/twitter/bootstrap/less/responsive&amp;quot;;
/**
 * Define our variables last, any variable declared here will be used in the includes above
 * which means that we can override any of the variables used in the bootstrap files easily
 * without modifying any of the core bootstrap files
 ******************************************************************************************
 */

// Scaffolding
// -------------------------
@bodyBackground:    #f2f2f2;
@textColor:       #575757;

// Links
// -------------------------
@linkColor:       #41a096;

// Typography
// -------------------------
@sansFontFamily:    Arial, Helvetica, sans-serif;
&lt;/pre&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;public/js/app.js&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Now we&amp;#8217;ll wrap all of our code in an immediately-invoking-anonymous-function that passes in a few global objects. We&amp;#8217;ll then alias these global objects to something more useful to us. Also, we&amp;#8217;ll cache a few jQuery objects inside the document ready function.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;//alias the global object
//alias jQuery so we can potentially use other libraries that utilize $
//alias Backbone to save us on some typing
(function(exports, $, bb){

  //document ready
  $(function(){

    /**
     ***************************************
     * Cached Globals
     ***************************************
     */
    var $window, $body, $document;

    $window  = $(window);
    $document = $(document);
    $body   = $('body');
  });//end document ready

}(this, jQuery, Backbone));
&lt;/pre&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;public/views/layouts/application.blade.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Next is just a simple HTML layout file. We&amp;#8217;re however using the &lt;code&gt;asset&lt;/code&gt; helper from Laravel to aid us in creating paths to our assets. It is good practice to use this type of helper, because if you ever happen to move your project into a sub-folder, all of your links will still work.&lt;/p&gt;&lt;p&gt;We made sure that we included all of our dependencies in this file, and also added the jQuery dependency. I chose to request jQuery from the Google CDN, because chances are the visiting user of this site will already have a copy from that CDN cached in their browser, saving us from having to complete the HTTP request for it.&lt;/p&gt;&lt;p&gt;One important thing to note here is the way in which we are nesting our view. Mustache does not have Block Sections like Blade does, so instead, the contents of the nested view will be made available under a variable with the name of the section. I will point this out when we render this view from our route.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
 &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
 &amp;lt;title&amp;gt;Laravel4 &amp;amp; Backbone | Nettuts&amp;lt;/title&amp;gt;
 &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;gt;
 &amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;A single page blog built using Backbone.js, Laravel, and Twitter Bootstrap&amp;quot;&amp;gt;
 &amp;lt;meta name=&amp;quot;author&amp;quot; content=&amp;quot;Conar Welsh&amp;quot;&amp;gt;

 &amp;lt;link href=&amp;quot;{{ asset('css/styles.css') }}&amp;quot; rel=&amp;quot;stylesheet&amp;quot;&amp;gt;

 &amp;lt;!-- HTML5 shim, for IE6-8 support of HTML5 elements --&amp;gt;
 &amp;lt;!--[if lt IE 9]&amp;gt;
 &amp;lt;script src=&amp;quot;{{ asset('js/html5shiv.js') }}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;![endif]--&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

 &amp;lt;div id=&amp;quot;notifications&amp;quot;&amp;gt;
 &amp;lt;/div&amp;gt;

 &amp;lt;div class=&amp;quot;navbar navbar-inverse navbar-fixed-top&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;navbar-inner&amp;quot;&amp;gt;
   &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
    &amp;lt;button type=&amp;quot;button&amp;quot; class=&amp;quot;btn btn-navbar&amp;quot; data-toggle=&amp;quot;collapse&amp;quot; data-target=&amp;quot;.nav-collapse&amp;quot;&amp;gt;
     &amp;lt;span class=&amp;quot;icon-bar&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
     &amp;lt;span class=&amp;quot;icon-bar&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
     &amp;lt;span class=&amp;quot;icon-bar&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/button&amp;gt;
    &amp;lt;a class=&amp;quot;brand&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Nettuts Tutorial&amp;lt;/a&amp;gt;
    &amp;lt;div class=&amp;quot;nav-collapse collapse&amp;quot;&amp;gt;
     &amp;lt;ul class=&amp;quot;nav&amp;quot;&amp;gt;
      &amp;lt;li class=&amp;quot;active&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Blog&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
     &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;&amp;lt;!--/.nav-collapse --&amp;gt;
   &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
 &amp;lt;/div&amp;gt;

 &amp;lt;div class=&amp;quot;container&amp;quot; data-role=&amp;quot;main&amp;quot;&amp;gt;
  {{--since we are using mustache as the view, it does not have a concept of sections like blade has, so instead of using @yield here, our nested view will just be a variable that we can echo--}}

  {{ $content }}

 &amp;lt;/div&amp;gt; &amp;lt;!-- /container --&amp;gt;

 &amp;lt;!-- Placed at the end of the document so the pages load faster --&amp;gt;
 &amp;lt;script src=&amp;quot;//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;!-- use Google CDN for jQuery to hopefully get a cached copy --&amp;gt;
 &amp;lt;script src=&amp;quot;{{ asset('node_modules/underscore/underscore-min.js') }}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;script src=&amp;quot;{{ asset('node_modules/backbone/backbone-min.js') }}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;script src=&amp;quot;{{ asset('node_modules/mustache/mustache.js') }}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;script src=&amp;quot;{{ asset('js/bootstrap.min.js') }}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;script src=&amp;quot;{{ asset('js/app.js') }}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
 @yield('scripts')
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;public/views/app.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Next is just a simple view that we&amp;#8217;ll nest into our layout.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;dl&amp;gt;
  &amp;lt;dt&amp;gt;Q. What did Biggie say when he watched inception?&amp;lt;/dt&amp;gt;
  &amp;lt;dd&amp;gt;A. &amp;quot;It was all a dream!&amp;quot;&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&lt;/pre&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;app/routes.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Laravel should have already provided you with a default route, all we&amp;#8217;re doing here is changing the name of the view which that route is going to render.&lt;/p&gt;&lt;p&gt;Remember from above, I told you that the nested view was going to be available under a variable named whatever the parent section was? Well, when you nest a view, the first parameter to the function is the section name:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;View::make('view.path')-&amp;gt;nest($sectionName, $nestedViewPath, $viewVariables);
&lt;/pre&gt;&lt;p&gt;In our &lt;code&gt;nest&lt;/code&gt; command we called the section &amp;quot;content&amp;quot;, that means if we echo &lt;code&gt;$content&lt;/code&gt; from our layout, we&amp;#8217;ll get the rendered contents of that view. If we were to do &lt;code&gt;return View::make(&amp;#39;layouts.application&amp;#39;)-&amp;gt;nest(&amp;#39;foobar&amp;#39;, &amp;#39;app&amp;#39;);&lt;/code&gt; then our nested view would be available under a variable named &lt;code&gt;$foobar&lt;/code&gt;.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

//backbone app route
Route::get('/', function()
{
  //change our view name to the view we created in a previous step
  //notice that we do not need to provide the .mustache extension
  return View::make('layouts.application')-&amp;gt;nest('content', 'app');
});
&lt;/pre&gt;&lt;p&gt;With all of our basic files in place, we can test to ensure everything went OK. Laravel 4 utilizes the new PHP web server to provide us with a great little development environment. So long to the days of having a million virtual hosts setup on your development machine for every project that you work on!&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note: make sure that you&amp;#8217;ve compiled your LESS file first!&lt;/p&gt;&lt;/blockquote&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;php artisan serve
&lt;/pre&gt;&lt;p&gt;If you followed along correctly, you should be laughing hysterically at my horrible sense of humor, and all of our assets should be properly included into the page.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Part 2: Laravel 4 JSON API&lt;/h2&gt;&lt;p&gt;Now we&amp;#8217;ll build the API that will power our Backbone application. Laravel 4 makes this process a breeze.&lt;/p&gt;&lt;h3&gt;API Guidelines&lt;/h3&gt;&lt;p&gt;First let&amp;#39;s go over a few general guidelines to keep in mind while we build our API:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Status Codes&lt;/strong&gt;: Responses should reply with proper status codes, fight the temptation to just place an &lt;code&gt;{ error: &amp;quot;this is an error message&amp;quot; }&lt;/code&gt; in the body of your response. Use the HTTP protocol to its fullest!&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;200&lt;/strong&gt;: success&lt;/li&gt;&lt;li&gt;&lt;strong&gt;201&lt;/strong&gt;: resource created&lt;/li&gt;&lt;li&gt;&lt;strong&gt;204&lt;/strong&gt;: success, but no content to return&lt;/li&gt;&lt;li&gt;&lt;strong&gt;400&lt;/strong&gt;: request not fulfilled //validation error&lt;/li&gt;&lt;li&gt;&lt;strong&gt;401&lt;/strong&gt;: not authenticated&lt;/li&gt;&lt;li&gt;&lt;strong&gt;403&lt;/strong&gt;: refusal to respond //wrong credentials, do not have permission (un-owned resource)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;404&lt;/strong&gt;: not found&lt;/li&gt;&lt;li&gt;&lt;strong&gt;500&lt;/strong&gt;: other error&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Methods&lt;/strong&gt;: Even though controllers will be serving different resources, they should still have very similar behavior. The more predictable your API is, the easier it is to implement and adopt.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;index&lt;/strong&gt;: Return a collection of resources.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;show&lt;/strong&gt;: Return a single resource.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;create&lt;/strong&gt;: Return a form. This form should detail out the required fields, validation, and labels as best as possible. As well as anything else needed to properly create a resource. Even though this is a JSON API, it is very useful to return a form here. Both a computer and a person can parse through this form, and very easily decipher which items are needed to fill out this form successsfully. This is a very easy way to &amp;#8220;document&amp;#8221; the needs of your API.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;store&lt;/strong&gt;: Store a new resource and return with the proper status code: 201.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;edit&lt;/strong&gt;: Return a form filled with the current state of a resource. This form should detail out the required fields, validation, and labels as best as possible. As well as anything else needed to properly edit a resource.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;update&lt;/strong&gt;: Update an existing resource and return with the proper status code.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;delete&lt;/strong&gt;: Delete an existing resource and return with the proper status code: 204.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Routing &amp;amp; Versioning&lt;/h3&gt;&lt;p&gt;API&amp;#39;s are designed to be around for a while. This is not like your website where you can just change its functionality at the drop of a dime. If you have programs that use your API, they are not going to be happy with you if you change things around and their program breaks. For this reason, it&amp;#8217;s important that you use versioning.&lt;/p&gt;&lt;p&gt;We can always create a &amp;quot;version two&amp;quot; with additional, or altered functionality, and allow our subscribing programs to opt-in to these changes, rather than be forced.&lt;/p&gt;&lt;p&gt;Laravel provides us with route groups that are perfect for this, place the following code &lt;em&gt;ABOVE&lt;/em&gt; our first route:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

//create a group of routes that will belong to APIv1
Route::group(array('prefix' =&amp;gt; 'v1'), function()
{
  //... insert API routes here...
});
&lt;/pre&gt;&lt;h3&gt;Generating Resources&lt;/h3&gt;&lt;p&gt;We&amp;#8217;re going to use Jeffrey Way&amp;#39;s generators to generate our resources. When we generate a resource, it will create the following items for us:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Controller&lt;/li&gt;&lt;li&gt;Model&lt;/li&gt;&lt;li&gt;Views (index.blade.php, show.blade.php, create.blade.php, edit.blade.php)&lt;/li&gt;&lt;li&gt;Migration&lt;/li&gt;&lt;li&gt;Seeds&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We&amp;#8217;re only going to need two resources for this app: a &lt;code&gt;Post&lt;/code&gt; resource and a &lt;code&gt;Comment&lt;/code&gt; resource.&lt;/p&gt;&lt;p&gt;Note: in a recent update to the generators, I have been receiving a permissions error due to the way my web servers are setup. To remedy this problem, you must allow write permissions to the folder that the generators write the temp file to.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;sudo chmod -R 755 vendor/way/generators/src/Way/
&lt;/pre&gt;&lt;p&gt;Run the &lt;code&gt;generate:resource&lt;/code&gt; command&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;php artisan generate:resource post --fields=&amp;quot;title:string, content:text, author_name:string&amp;quot;

php artisan generate:resource comment --fields=&amp;quot;content:text, author_name:string, post_id:integer&amp;quot;
&lt;/pre&gt;&lt;p&gt;You should now pause for a second to investigate all of the files that the generator created for us.&lt;/p&gt;&lt;h3&gt;Adjust the Generated Resources&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;generate:resource&lt;/code&gt; command saved us a lot of work, but due to our unique configuration, we&amp;#8217;re still going to need to make some modifications.&lt;/p&gt;&lt;p&gt;First of all, the generator placed the views it created in the &lt;code&gt;app/views&lt;/code&gt; folder, so we need to move them to the &lt;code&gt;public/views&lt;/code&gt; folder&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;mv app/views/posts public/views/posts
mv app/views/comments public/views/comments
&lt;/pre&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;app/routes.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We decided that we wanted our API to be versioned, so we&amp;#8217;ll need to move the routes that the generator created for us into the version group. We&amp;#8217;ll also want to namespace our controllers with the corresponding version, so that we can have a different set of controllers for each version we build. Also the comments resource needs to be nested under the posts resource.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

//create a group of routes that will belong to APIv1
Route::group(array('prefix' =&amp;gt; 'v1'), function()
{
  //... insert API routes here...
  Route::resource('posts', 'V1\PostsController'); //notice the namespace
  Route::resource('posts.comments', 'V1\PostsCommentsController'); //notice the namespace, and the nesting
});

//backbone app route
Route::get('/', function()
{
  //change our view name to the view we created in a previous step
  //notice that we do not need to provide the .mustache extension
  return View::make('layouts.application')-&amp;gt;nest('content', 'app');
});
&lt;/pre&gt;&lt;p&gt;Since we namespaced our controllers, we should move them into their own folder for organization, let&amp;#39;s create a folder named &lt;code&gt;V1&lt;/code&gt; and move our generated controllers into it. Also, since we nested our comments controller under the posts controller, let&amp;#39;s change the name of that controller to reflect the relationship.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;mkdir app/controllers/V1
mv app/controllers/PostsController.php app/controllers/V1/
mv app/controllers/CommentsController.php app/controllers/V1/PostsCommentsController.php
&lt;/pre&gt;&lt;p&gt;We&amp;#8217;ll need to update the controller files to reflect our changes as well. First of all, we need to namespace them, and since they are namespaced, any classes outside of that namespace will need to be manually imported with the &lt;code&gt;use&lt;/code&gt; statement.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/controllers/PostsController.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php
//use our new namespace
namespace V1;

//import classes that are not in this new namespace
use BaseController;

class PostsController extends BaseController {
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/controllers/PostsCommentsController.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We also need to update our &lt;code&gt;CommentsController&lt;/code&gt; with our new name: &lt;code&gt;PostsCommentsController&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php
//use our new namespace
namespace V1;

//import classes that are not in this new namespace
use BaseController;

//rename our controller class
class PostsCommentsController extends BaseController {
&lt;/pre&gt;&lt;h3&gt;Adding in Repositories&lt;/h3&gt;&lt;p&gt;By default, repositories are not part of Laravel. Laravel is extremely flexible though, and makes it very easy to add them in. We&amp;#8217;re going to use repositories to help us separate our logic for code re-usability, as well as for testing. For now we&amp;#8217;ll just get setup to use repositories, we&amp;#8217;ll add in the proper logic later.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s make a folder to store our repositories in:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;mkdir app/repositories
&lt;/pre&gt;&lt;p&gt;To let our auto-loader know about this new folder, we need to add it to our &lt;code&gt;composer.json&lt;/code&gt; file. Take a look at the updated &amp;quot;autoload&amp;quot; section of our file, and you&amp;#8217;ll see that we added in the repositories folder.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;composer.json&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;{
  &amp;quot;require&amp;quot;: {
    &amp;quot;laravel/framework&amp;quot;: &amp;quot;4.0.*&amp;quot;,
    &amp;quot;way/generators&amp;quot;: &amp;quot;dev-master&amp;quot;,
    &amp;quot;twitter/bootstrap&amp;quot;: &amp;quot;dev-master&amp;quot;,
    &amp;quot;conarwelsh/mustache-l4&amp;quot;: &amp;quot;dev-master&amp;quot;
  },
  &amp;quot;require-dev&amp;quot;: {
    &amp;quot;phpunit/phpunit&amp;quot;: &amp;quot;3.7.*&amp;quot;,
    &amp;quot;mockery/mockery&amp;quot;: &amp;quot;0.7.*&amp;quot;
  },
  &amp;quot;autoload&amp;quot;: {
    &amp;quot;classmap&amp;quot;: [
      &amp;quot;app/commands&amp;quot;,
      &amp;quot;app/controllers&amp;quot;,
      &amp;quot;app/models&amp;quot;,
      &amp;quot;app/database/migrations&amp;quot;,
      &amp;quot;app/database/seeds&amp;quot;,
      &amp;quot;app/tests/TestCase.php&amp;quot;,
      &amp;quot;app/repositories&amp;quot;
    ]
  },
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;post-update-cmd&amp;quot;: &amp;quot;php artisan optimize&amp;quot;
  },
  &amp;quot;minimum-stability&amp;quot;: &amp;quot;dev&amp;quot;
}
&lt;/pre&gt;&lt;h3&gt;Seeding Our Database&lt;/h3&gt;&lt;p&gt;Database seeds are a useful tool, they provide us with an easy way to fill our database with some content. The generators provided us with base files for seeding, we merely need to add in some actual seeds.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/database/seeds/PostsTableSeeder.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class PostsTableSeeder extends Seeder {

  public function run()
  {
    $posts = array(
      array(
        'title'    =&amp;gt; 'Test Post',
        'content'   =&amp;gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',
        'author_name' =&amp;gt; 'Conar Welsh',
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
      array(
        'title'    =&amp;gt; 'Another Test Post',
        'content'   =&amp;gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',
        'author_name' =&amp;gt; 'Conar Welsh',
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
    );

    // Uncomment the below to run the seeder
    DB::table('posts')-&amp;gt;insert($posts);
  }

}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/database/seeds/CommentsTableSeeder.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class CommentsTableSeeder extends Seeder {

  public function run()
  {
    $comments = array(
      array(
        'content'   =&amp;gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',
        'author_name' =&amp;gt; 'Testy McTesterson',
        'post_id'   =&amp;gt; 1,
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
      array(
        'content'   =&amp;gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',
        'author_name' =&amp;gt; 'Testy McTesterson',
        'post_id'   =&amp;gt; 1,
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
      array(
        'content'   =&amp;gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',
        'author_name' =&amp;gt; 'Testy McTesterson',
        'post_id'   =&amp;gt; 2,
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
    );

    // Uncomment the below to run the seeder
    DB::table('comments')-&amp;gt;insert($comments);
  }

}
&lt;/pre&gt;&lt;p&gt;Don&amp;#8217;t forget to run &lt;code&gt;composer dump-autoload&lt;/code&gt; to let the Composer auto loader know about the new migration files!&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;composer dump-autoload
&lt;/pre&gt;&lt;p&gt;Now we can run our migrations and seed the database. Laravel provides us with a single command to do both:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;php artisan migrate --seed
&lt;/pre&gt;&lt;h3&gt;Tests&lt;/h3&gt;&lt;p&gt;Testing is one of those topics in development that no one can argue the importance of, however most people tend to ignore it due to the learning curve. Testing is really not that difficult and it can dramatically improve your application. For this tutorial, we&amp;#8217;ll setup some basic tests to help us ensure that our API is functioning properly. We&amp;#8217;ll build this API TDD style. The rules of TDD state that we are not allowed to write any production code until we have failing tests that warrants it. However, if I were to walk you through each test individually, this would prove to be a very long tutorial, so in the interest of brevity, I will just provide you with some tests to work from, and then the correct code to make those tests pass afterwards.&lt;/p&gt;&lt;p&gt;Before we write any tests though, we should first check the current test status of our application. Since we installed PHPUnit via composer, we have the binaries available to us to use. All you need to do is run:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;vendor/phpunit/phpunit/phpunit.php
&lt;/pre&gt;&lt;p&gt;Whoops! We already have a failure! The test that is failing is actually an example test that comes pre-installed in our Laravel application structure, this tests against the default route that was also installed with the Laravel application structure. Since we modified this route, we cannot be surprised that the test failed. We can however, just delete this test altogether as it does not apply to our application.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;rm app/tests/ExampleTest.php
&lt;/pre&gt;&lt;p&gt;If you run the PHPUnit command again, you will see that no tests were executed, and we have a clean slate for testing.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note: it is possible that if you have an older version of Jeffrey Way&amp;#39;s generators that you&amp;#8217;ll actually have a few tests in there that were created by those generators, and those tests are probably failing. Just delete or overwrite those tests with the ones found below to proceed.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;For this tutorial we&amp;#8217;ll be testing our controllers and our repositories. Let&amp;#39;s create a few folders to store these tests in:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;mkdir app/tests/controllers app/tests/repositories
&lt;/pre&gt;&lt;p&gt;Now for the test files. We&amp;#8217;re going to use Mockery to mock our repositories for our controller tests. Mockery objects do as their name implies, they &amp;quot;mock&amp;quot; objects and report back to us on how those objects were interacted with.&lt;/p&gt;&lt;p&gt;In the case of the controller tests, we do not actually want the repositories to be called, after all, these are the controller tests, not the repository tests. So Mockery will set us up objects to use &lt;em&gt;instead&lt;/em&gt; of our repositories, and let us know whether or not those objects were called as we expected them to.&lt;/p&gt;&lt;p&gt;In order to pull this off, we&amp;#8217;ll have to tell the controllers to use our &amp;quot;mocked&amp;quot; objects as opposed to the real things. We&amp;#8217;ll just tell our Application to use a mocked instance next time a certain class is requested. The command looks like this:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;App::instance($classToReplace, $instanceOfClassToReplaceWith);
&lt;/pre&gt;&lt;p&gt;The overall mocking process will go something like this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Create a new Mockery object, providing it the name of the class which it is to mock.&lt;/li&gt;&lt;li&gt;Tell the Mockery object which methods it should expect to receive, how many times it should receive that method, and what that method should return.&lt;/li&gt;&lt;li&gt;Use the command shown above to tell our Application to use this new Mockery object instead of the default.&lt;/li&gt;&lt;li&gt;Run the controller method like usual.&lt;/li&gt;&lt;li&gt;Assert the response.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;app/tests/controllers/CommentsControllerTest.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class CommentsControllerTest extends TestCase {

  /**
   ************************************************************************
   * Basic Route Tests
   * notice that we can use our route() helper here!
   ************************************************************************
   */

  //test that GET /v1/posts/1/comments returns HTTP 200
  public function testIndex()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.index', array(1)) );
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  //test that GET /v1/posts/1/comments/1 returns HTTP 200
  public function testShow()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.show', array(1,1)) );
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  //test that GET /v1/posts/1/comments/create returns HTTP 200
  public function testCreate()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.create', array(1)) );
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  //test that GET /v1/posts/1/comments/1/edit returns HTTP 200
  public function testEdit()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.edit', array(1,1)) );
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  /**
   *************************************************************************
   * Tests to ensure that the controller calls the repo as we expect
   * notice we are &amp;quot;Mocking&amp;quot; our repository
   *
   * also notice that we do not really care about the data or interactions
   * we merely care that the controller is doing what we are going to want
   * it to do, which is reach out to our repository for more information
   *************************************************************************
   */

  //ensure that the index function calls our repository's &amp;quot;findAll&amp;quot; method
  public function testIndexShouldCallFindAllMethod()
  {
    //create our new Mockery object with a name of CommentRepositoryInterface
    $mock = Mockery::mock('CommentRepositoryInterface');

    //inform the Mockery object that the &amp;quot;findAll&amp;quot; method should be called on it once
    //and return a string value of &amp;quot;foo&amp;quot;
    $mock-&amp;gt;shouldReceive('findAll')-&amp;gt;once()-&amp;gt;andReturn('foo');

    //inform our application that we have an instance that it should use
    //whenever the CommentRepositoryInterface is requested
    App::instance('CommentRepositoryInterface', $mock);

    //call our controller route
    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.index', array(1)));

    //assert that the response is a boolean value of true
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  //ensure that the show method calls our repository's &amp;quot;findById&amp;quot; method
  public function testShowShouldCallFindById()
  {
    $mock = Mockery::mock('CommentRepositoryInterface');
    $mock-&amp;gt;shouldReceive('findById')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('CommentRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.show', array(1,1)));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  //ensure that our create method calls the &amp;quot;instance&amp;quot; method on the repository
  public function testCreateShouldCallInstanceMethod()
  {
    $mock = Mockery::mock('CommentRepositoryInterface');
    $mock-&amp;gt;shouldReceive('instance')-&amp;gt;once()-&amp;gt;andReturn(array());
    App::instance('CommentRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.create', array(1)));
    $this-&amp;gt;assertViewHas('comment');
  }

  //ensure that the edit method calls our repository's &amp;quot;findById&amp;quot; method
  public function testEditShouldCallFindByIdMethod()
  {
    $mock = Mockery::mock('CommentRepositoryInterface');
    $mock-&amp;gt;shouldReceive('findById')-&amp;gt;once()-&amp;gt;andReturn(array());
    App::instance('CommentRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.comments.edit', array(1,1)));
    $this-&amp;gt;assertViewHas('comment');
  }

  //ensure that the store method should call the repository's &amp;quot;store&amp;quot; method
  public function testStoreShouldCallStoreMethod()
  {
    $mock = Mockery::mock('CommentRepositoryInterface');
    $mock-&amp;gt;shouldReceive('store')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('CommentRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('POST', route('v1.posts.comments.store', array(1)));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  //ensure that the update method should call the repository's &amp;quot;update&amp;quot; method
  public function testUpdateShouldCallUpdateMethod()
  {
    $mock = Mockery::mock('CommentRepositoryInterface');
    $mock-&amp;gt;shouldReceive('update')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('CommentRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('PUT', route('v1.posts.comments.update', array(1,1)));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  //ensure that the destroy method should call the repositories &amp;quot;destroy&amp;quot; method
  public function testDestroyShouldCallDestroyMethod()
  {
    $mock = Mockery::mock('CommentRepositoryInterface');
    $mock-&amp;gt;shouldReceive('destroy')-&amp;gt;once()-&amp;gt;andReturn(true);
    App::instance('CommentRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('DELETE', route('v1.posts.comments.destroy', array(1,1)));
    $this-&amp;gt;assertTrue( empty($response-&amp;gt;original) );
  }
}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/tests/controllers/PostsControllerTest.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Next, we&amp;#8217;ll follow the exact same procedure for the &lt;code&gt;PostsController&lt;/code&gt; tests&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class PostsControllerTest extends TestCase {

  /**
   * Test Basic Route Responses
   */
  public function testIndex()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.index'));
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  public function testShow()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.show', array(1)));
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  public function testCreate()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.create'));
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  public function testEdit()
  {
    $response = $this-&amp;gt;call('GET', route('v1.posts.edit', array(1)));
    $this-&amp;gt;assertTrue($response-&amp;gt;isOk());
  }

  /**
   * Test that controller calls repo as we expect
   */
  public function testIndexShouldCallFindAllMethod()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('findAll')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.index'));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  public function testShowShouldCallFindById()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('findById')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.show', array(1)));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  public function testCreateShouldCallInstanceMethod()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('instance')-&amp;gt;once()-&amp;gt;andReturn(array());
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.create'));
    $this-&amp;gt;assertViewHas('post');
  }

  public function testEditShouldCallFindByIdMethod()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('findById')-&amp;gt;once()-&amp;gt;andReturn(array());
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('GET', route('v1.posts.edit', array(1)));
    $this-&amp;gt;assertViewHas('post');
  }

  public function testStoreShouldCallStoreMethod()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('store')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('POST', route('v1.posts.store'));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  public function testUpdateShouldCallUpdateMethod()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('update')-&amp;gt;once()-&amp;gt;andReturn('foo');
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('PUT', route('v1.posts.update', array(1)));
    $this-&amp;gt;assertTrue(!! $response-&amp;gt;original);
  }

  public function testDestroyShouldCallDestroyMethod()
  {
    $mock = Mockery::mock('PostRepositoryInterface');
    $mock-&amp;gt;shouldReceive('destroy')-&amp;gt;once()-&amp;gt;andReturn(true);
    App::instance('PostRepositoryInterface', $mock);

    $response = $this-&amp;gt;call('DELETE', route('v1.posts.destroy', array(1)));
    $this-&amp;gt;assertTrue( empty($response-&amp;gt;original) );
  }

}
&lt;/pre&gt;&lt;hr
/&gt;&lt;p&gt;&lt;strong&gt;app/tests/repositories/EloquentCommentRepositoryTest.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Now for the repository tests. In writing our controller tests, we pretty much already decided what most of the interface should look like for the repositories. Our controllers needed the following methods:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;findById($id)&lt;/li&gt;&lt;li&gt;findAll()&lt;/li&gt;&lt;li&gt;instance($data)&lt;/li&gt;&lt;li&gt;store($data)&lt;/li&gt;&lt;li&gt;update($id, $data)&lt;/li&gt;&lt;li&gt;destroy($id)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The only other method that we&amp;#8217;ll want to add here is a &lt;code&gt;validate&lt;/code&gt; method. This will mainly be a private method for the repository to ensure that the data is safe to store or update.&lt;/p&gt;&lt;p&gt;For these tests, we&amp;#8217;re also going to add a &lt;code&gt;setUp&lt;/code&gt; method, which will allow us to run some code on our class, prior to the execution of &lt;em&gt;each&lt;/em&gt; test. Our &lt;code&gt;setUp&lt;/code&gt; method will be a very simple one, we&amp;#8217;ll just make sure that any &lt;code&gt;setUp&lt;/code&gt; methods defined in parent classes are also called using &lt;code&gt;parent::setUp()&lt;/code&gt; and then simply add a class variable that stores an instance of our repository.&lt;/p&gt;&lt;p&gt;We&amp;#8217;ll use the power of Laravel&amp;#39;s IoC container again to get an instance of our repository. The &lt;code&gt;App::make()&lt;/code&gt; command will return an instance of the requested class, now it may seem strange that we do not just do &lt;code&gt;$this-&amp;gt;repo = new EloquentCommentRepository()&lt;/code&gt;, but hold that thought, we&amp;#8217;ll come back to it momentarily. You probably noticed that we&amp;#8217;re asking for a class called &lt;code&gt;EloquentCommentRepository&lt;/code&gt;, but in our controller tests above, we were calling our repository &lt;code&gt;CommentRepositoryInterface&lt;/code&gt;&amp;#8230; put this thought on the back-burner as well&amp;#8230; explainations for both are coming, I promise!&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class EloquentCommentRepositoryTest extends TestCase {

  public function setUp()
  {
    parent::setUp();
    $this-&amp;gt;repo = App::make('EloquentCommentRepository');
  }

  public function testFindByIdReturnsModel()
  {
    $comment = $this-&amp;gt;repo-&amp;gt;findById(1,1);
    $this-&amp;gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);
  }

  public function testFindAllReturnsCollection()
  {
    $comments = $this-&amp;gt;repo-&amp;gt;findAll(1);
    $this-&amp;gt;assertTrue($comments instanceof Illuminate\Database\Eloquent\Collection);
  }

  public function testValidatePasses()
  {
    $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
      'post_id'   =&amp;gt; 1,
      'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',
      'author_name' =&amp;gt; 'Testy McTesterson'
    ));

    $this-&amp;gt;assertTrue($reply);
  }

  public function testValidateFailsWithoutContent()
  {
    try {
      $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
        'post_id'   =&amp;gt; 1,
        'author_name' =&amp;gt; 'Testy McTesterson'
      ));
    }
    catch(ValidationException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('ValidationException was not raised');
  }

  public function testValidateFailsWithoutAuthorName()
  {
    try {
      $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
        'post_id'   =&amp;gt; 1,
        'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.'
      ));
    }
    catch(ValidationException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('ValidationException was not raised');
  }

  public function testValidateFailsWithoutPostId()
  {
    try {
      $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
        'author_name' =&amp;gt; 'Testy McTesterson',
        'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.'
      ));
    }
    catch(ValidationException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('ValidationException was not raised');
  }

  public function testStoreReturnsModel()
  {
    $comment_data = array(
      'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',
      'author_name' =&amp;gt; 'Testy McTesterson'
    );

    $comment = $this-&amp;gt;repo-&amp;gt;store(1, $comment_data);

    $this-&amp;gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);
    $this-&amp;gt;assertTrue($comment-&amp;gt;content === $comment_data['content']);
    $this-&amp;gt;assertTrue($comment-&amp;gt;author_name === $comment_data['author_name']);
  }

  public function testUpdateSaves()
  {
    $comment_data = array(
      'content' =&amp;gt; 'The Content Has Been Updated'
    );

    $comment = $this-&amp;gt;repo-&amp;gt;update(1, 1, $comment_data);

    $this-&amp;gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);
    $this-&amp;gt;assertTrue($comment-&amp;gt;content === $comment_data['content']);
  }

  public function testDestroySaves()
  {
    $reply = $this-&amp;gt;repo-&amp;gt;destroy(1,1);
    $this-&amp;gt;assertTrue($reply);

    try {
      $this-&amp;gt;repo-&amp;gt;findById(1,1);
    }
    catch(NotFoundException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('NotFoundException was not raised');
  }

  public function testInstanceReturnsModel()
  {
    $comment = $this-&amp;gt;repo-&amp;gt;instance();
    $this-&amp;gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);
  }

  public function testInstanceReturnsModelWithData()
  {
    $comment_data = array(
      'title' =&amp;gt; 'Un-validated title'
    );

    $comment = $this-&amp;gt;repo-&amp;gt;instance($comment_data);
    $this-&amp;gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);
    $this-&amp;gt;assertTrue($comment-&amp;gt;title === $comment_data['title']);
  }

}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/tests/repositories/EloquentPostRepositoryTest.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class EloquentPostRepositoryTest extends TestCase {

  public function setUp()
  {
    parent::setUp();
    $this-&amp;gt;repo = App::make('EloquentPostRepository');
  }

  public function testFindByIdReturnsModel()
  {
    $post = $this-&amp;gt;repo-&amp;gt;findById(1);
    $this-&amp;gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);
  }

  public function testFindAllReturnsCollection()
  {
    $posts = $this-&amp;gt;repo-&amp;gt;findAll();
    $this-&amp;gt;assertTrue($posts instanceof Illuminate\Database\Eloquent\Collection);
  }

  public function testValidatePasses()
  {
    $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
      'title'    =&amp;gt; 'This Should Pass',
      'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',
      'author_name' =&amp;gt; 'Testy McTesterson'
    ));

    $this-&amp;gt;assertTrue($reply);
  }

  public function testValidateFailsWithoutTitle()
  {
    try {
      $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
        'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',
        'author_name' =&amp;gt; 'Testy McTesterson'
      ));
    }
    catch(ValidationException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('ValidationException was not raised');
  }

  public function testValidateFailsWithoutAuthorName()
  {
    try {
      $reply = $this-&amp;gt;repo-&amp;gt;validate(array(
        'title'    =&amp;gt; 'This Should Pass',
        'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.'
      ));
    }
    catch(ValidationException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('ValidationException was not raised');
  }

  public function testStoreReturnsModel()
  {
    $post_data = array(
      'title'    =&amp;gt; 'This Should Pass',
      'content'   =&amp;gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',
      'author_name' =&amp;gt; 'Testy McTesterson'
    );

    $post = $this-&amp;gt;repo-&amp;gt;store($post_data);

    $this-&amp;gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);
    $this-&amp;gt;assertTrue($post-&amp;gt;title === $post_data['title']);
    $this-&amp;gt;assertTrue($post-&amp;gt;content === $post_data['content']);
    $this-&amp;gt;assertTrue($post-&amp;gt;author_name === $post_data['author_name']);
  }

  public function testUpdateSaves()
  {
    $post_data = array(
      'title' =&amp;gt; 'The Title Has Been Updated'
    );

    $post = $this-&amp;gt;repo-&amp;gt;update(1, $post_data);

    $this-&amp;gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);
    $this-&amp;gt;assertTrue($post-&amp;gt;title === $post_data['title']);
  }

  public function testDestroySaves()
  {
    $reply = $this-&amp;gt;repo-&amp;gt;destroy(1);
    $this-&amp;gt;assertTrue($reply);

    try {
      $this-&amp;gt;repo-&amp;gt;findById(1);
    }
    catch(NotFoundException $expected)
    {
      return;
    }

    $this-&amp;gt;fail('NotFoundException was not raised');
  }

  public function testInstanceReturnsModel()
  {
    $post = $this-&amp;gt;repo-&amp;gt;instance();
    $this-&amp;gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);
  }

  public function testInstanceReturnsModelWithData()
  {
    $post_data = array(
      'title' =&amp;gt; 'Un-validated title'
    );

    $post = $this-&amp;gt;repo-&amp;gt;instance($post_data);
    $this-&amp;gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);
    $this-&amp;gt;assertTrue($post-&amp;gt;title === $post_data['title']);
  }

}
&lt;/pre&gt;&lt;p&gt;Now that we have all of our tests in place, let&amp;#39;s run PHPUnit again to watch them fail!&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;vendor/phpunit/phpunit/phpunit.php
&lt;/pre&gt;&lt;p&gt;You should have a whole ton of failures, and in fact, the test suite probably did not even finish testing before it crashed. This is OK, that means we have followed the rules of TDD and wrote failing tests before production code. Although, typically these tests would be written one at a time and you would not move on to the next test until you had code that allowed the previous test to pass. Your terminal should probably look something like mine at the moment:&lt;/p&gt; &lt;figure
class='tutorial_image'&gt;&lt;img
src='https://raw.github.com/conarwelsh/nettuts-laravel4-and-backbone/master/public/img/first-failed-screenshot.png' alt='Screenshot'&gt;&lt;/figure&gt;&lt;p&gt;What&amp;#8217;s actually failing is the &lt;code&gt;assertViewHas&lt;/code&gt; method in our controller tests. It&amp;#8217;s kind of intimidating to deal with this kind of an error when we have lumped together all of our tests without any production code at all. This is why you should always write the tests one at a time, as you&amp;#8217;ll find these errors in stride, as opposed to just a huge mess of errors at once. For now, just follow my lead into the implementation of our code.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Sidebar Discussion&lt;/h2&gt;&lt;p&gt;Before we proceed with the implementations, let&amp;#39;s break for a quick sidebar discussion on the responsibilities of the MVC pattern.&lt;/p&gt;&lt;p&gt;From &lt;a
href="http://www.amazon.com/Design-Patterns-Object-Oriented-Professional-Computing/dp/0201634988"&gt;The Gang of Four&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;The Model is the application object, the View is its screen presentation, and the Controller defines the way the user interface reacts to user input.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The point of using a structure like this is to remain encapsulated and flexible, allowing us to exchange and reuse components. Let&amp;#39;s go through each part of the MVC pattern and talk about its reusability and flexibility:&lt;/p&gt;&lt;h4&gt;View&lt;/h4&gt;&lt;p&gt;I think most people would agree that a View is supposed to be a simple visual representation of data and should not contain much logic. In our case, as developers for the web, our View tends to be HTML or XML.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;reusable&lt;/strong&gt;: always, almost anything can create a view&lt;/li&gt;&lt;li&gt;&lt;strong&gt;flexible&lt;/strong&gt;: not having any real logic in these layers makes this very flexible&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Controller&lt;/h4&gt;&lt;p&gt;If a Controller &amp;quot;defines the way the user interface reacts to user input&amp;quot;, then its responsibility should be to listen to user input (GET, POST, Headers, etc), and build out the current state of the application. In my opinion, a Controller should be very light and should not contain more code than is required to accomplish the above.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;reusable&lt;/strong&gt;: We have to remember that our Controllers return an opinionated View, so we cannot ever call that Controller method in a practical way to use any of the logic inside it. Therefore any logic placed in Controller methods, must be specific to that Controller method, if the logic is reusable, it should be placed elsewhere.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;flexible&lt;/strong&gt;: In most PHP MVCs, the Controller is tied directly to the route, which does not leave us very much flexibility. Laravel fixes this issue by allowing us to declare routes that use a controller, so we can now swap out our controllers with different implementations if need be:&lt;/li&gt;&lt;/ul&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;Route::get('/', array(
  'uses' =&amp;gt; 'SomeController@action'
));
&lt;/pre&gt;&lt;h4&gt;Model&lt;/h4&gt;&lt;p&gt;The Model is the &amp;quot;application object&amp;quot; in our definition from the Gang of Four. This is a very generic definition. In addition, we just decided to offload any logic that needs to be reusable from our Controller, and since the Model is the only component left in our defined structure, it&amp;#8217;s logical to assume that this is the new home for that logic. However, I think the Model should not contain any logic like this. In my opinion, we should think of our &amp;quot;application object&amp;quot;, in this case as an object that represents its place in the data-layer, whether that be a table, row, or collection entirely depends on state. The model should contain not much more than getters and setters for data (including relationships).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;reusable&lt;/strong&gt;: If we follow the above practice and make our Models be an object that represents its place in the database, this object remains very reusable. Any part of our system can use this model and by doing so gain complete and unopinionated access to the database.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;flexible&lt;/strong&gt;: Following the above practice, our Model is basically an implementation of an ORM, this allows us to be flexible, because we now have the power to change ORM&amp;#39;s whenever we&amp;#8217;d like to just by adding a new Model. We should probably have a pre-defined interface that our Model&amp;#39;s must abide by, such as: all, find, create, update, delete. Implementation of a new ORM would be as simple as ensuring that the previously mentioned interface was accomodated.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Repository&lt;/h4&gt;&lt;p&gt;Just by carefully defining our MVC components, we orphaned all kinds of logic into no-man&amp;#39;s land. This is where Repositories come in to fill the void. Repositories become the intermediary of the Controllers and Models. A typical request would be something like this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The Controller receives all user input and passes it to the repository.&lt;/li&gt;&lt;li&gt;The Repository does any &amp;quot;pre-gathering&amp;quot; actions such as validation of data, authorization, authentication, etc. If these &amp;quot;pre-gathering&amp;quot; actions are successful, then the request is passed to the Model for processing.&lt;/li&gt;&lt;li&gt;The Model will process all of the data into the data-layer, and return the current state.&lt;/li&gt;&lt;li&gt;The Repository will handle any &amp;quot;post-gathering&amp;quot; routines and return the current state to the controller.&lt;/li&gt;&lt;li&gt;The Controller will then create the appropriate view using the information provided by the repository.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Our Repository ends up as flexible and organized as we have made our Controllers and Models, allowing us to reuse this in most parts of our system, as well as being able to swap it out for another implementation if needed.&lt;/p&gt;&lt;p&gt;We have already seen an example of swapping out a repository for another implementation in the Controller tests above. Instead of using our default Repository, we asked the IoC container to provide the controller with an instance of a Mockery object. We have this same power for all of our components.&lt;/p&gt;&lt;p&gt;What we have accomplised here by adding another layer to our MVC, is a very organized, scalable, and testable system. Let&amp;#39;s start putting the pieces in place and getting our tests to pass.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Controller Implementation&lt;/h2&gt;&lt;p&gt;If you take a read through the controller tests, you&amp;#8217;ll see that all we really care about is how the controller is interacting with the repository. So let&amp;#39;s see how light and simple that makes our controllers.&lt;/p&gt;&lt;p&gt;Note: in TDD, the objective is to do no more work than is required to make your tests pass. So we want to do the absolute bare minimum here.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/controllers/V1/PostsController.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php
namespace V1;

use BaseController; 
use PostRepositoryInterface; 
use Input;
use View;

class PostsController extends BaseController {

  /**
   * We will use Laravel's dependency injection to auto-magically
   * &amp;quot;inject&amp;quot; our repository instance into our controller
   */
  public function __construct(PostRepositoryInterface $posts)
  {
    $this-&amp;gt;posts = $posts;
  }

  /**
   * Display a listing of the resource.
   *
   * @return Response
   */
  public function index()
  {
    return $this-&amp;gt;posts-&amp;gt;findAll();
  }

  /**
   * Show the form for creating a new resource.
   *
   * @return Response
   */
  public function create()
  {
    $post = $this-&amp;gt;posts-&amp;gt;instance();
    return View::make('posts._form', compact('post'));
  }

  /**
   * Store a newly created resource in storage.
   *
   * @return Response
   */
  public function store()
  {
    return $this-&amp;gt;posts-&amp;gt;store( Input::all() );
  }

  /**
   * Display the specified resource.
   *
   * @param int $id
   * @return Response
   */
  public function show($id)
  {
    return $this-&amp;gt;posts-&amp;gt;findById($id);
  }

  /**
   * Show the form for editing the specified resource.
   *
   * @param int $id
   * @return Response
   */
  public function edit($id)
  {
    $post = $this-&amp;gt;posts-&amp;gt;findById($id);
    return View::make('posts._form', compact('post'));
  }

  /**
   * Update the specified resource in storage.
   *
   * @param int $id
   * @return Response
   */
  public function update($id)
  {
    return $this-&amp;gt;posts-&amp;gt;update($id, Input::all());
  }

  /**
   * Remove the specified resource from storage.
   *
   * @param int $id
   * @return Response
   */
  public function destroy($id)
  {
    $this-&amp;gt;posts-&amp;gt;destroy($id);
    return '';
  }

}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/controllers/PostsCommentsController.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php
namespace V1;

use BaseController; 
use CommentRepositoryInterface; 
use Input;
use View;

class PostsCommentsController extends BaseController {

  /**
   * We will use Laravel's dependency injection to auto-magically
   * &amp;quot;inject&amp;quot; our repository instance into our controller
   */
  public function __construct(CommentRepositoryInterface $comments)
  {
    $this-&amp;gt;comments = $comments;
  }

  /**
   * Display a listing of the resource.
   *
   * @return Response
   */
  public function index($post_id)
  {
    return $this-&amp;gt;comments-&amp;gt;findAll($post_id);
  }

  /**
   * Show the form for creating a new resource.
   *
   * @return Response
   */
  public function create($post_id)
  {
    $comment = $this-&amp;gt;comments-&amp;gt;instance(array(
      'post_id' =&amp;gt; $post_id
    ));

    return View::make('comments._form', compact('comment'));
  }

  /**
   * Store a newly created resource in storage.
   *
   * @return Response
   */
  public function store($post_id)
  {
    return $this-&amp;gt;comments-&amp;gt;store( $post_id, Input::all() );
  }

  /**
   * Display the specified resource.
   *
   * @param int $id
   * @return Response
   */
  public function show($post_id, $id)
  {
    return $this-&amp;gt;comments-&amp;gt;findById($post_id, $id);
  }

  /**
   * Show the form for editing the specified resource.
   *
   * @param int $id
   * @return Response
   */
  public function edit($post_id, $id)
  {
    $comment = $this-&amp;gt;comments-&amp;gt;findById($post_id, $id);

    return View::make('comments._form', compact('comment'));
  }

  /**
   * Update the specified resource in storage.
   *
   * @param int $id
   * @return Response
   */
  public function update($post_id, $id)
  {
    return $this-&amp;gt;comments-&amp;gt;update($post_id, $id, Input::all());
  }

  /**
   * Remove the specified resource from storage.
   *
   * @param int $id
   * @return Response
   */
  public function destroy($post_id, $id)
  {
    $this-&amp;gt;comments-&amp;gt;destroy($post_id, $id);
    return '';
  }

}
&lt;/pre&gt;&lt;p&gt;It doesn&amp;#8217;t get much simpler than that, all the Controllers are doing is handing the input data to the repository, taking the response from that, and handing it to the View, the View in our case is merely JSON for most of our methods. When we return an Eloquent Collection, or Eloquent Model from a Controller in Laravel 4, the object is parsed into JSON auto-magically, which makes our job very easy.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note: notice that we added a few more &amp;quot;use&amp;quot; statements to the top of the file to support the other classes that we&amp;#8217;re using. Do not forget this when you&amp;#8217;re working within a namespace.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The only thing that is a bit tricky in this controller is the constructor. Notice we&amp;#8217;re passing in a typed variable as a dependency for this Controller, yet there is no point that we have access to the instantiation of this controller to actually insert that class&amp;#8230; welcome to dependency injection! What we&amp;#8217;re actually doing here is hinting to our controller that we have a dependency needed to run this class and what its class name is (or its IoC binding name). Laravel uses &lt;code&gt;App::make()&lt;/code&gt; to create its Controllers before calling them. &lt;code&gt;App::make()&lt;/code&gt; will try to resolve an item by looking for any bindings that we may have declared, and/or using the auto-loader to provide an instance. In addition, it will also resolve any dependencies needed to instantiate that class for us, by more-or-less recursively calling &lt;code&gt;App::make()&lt;/code&gt; on each of the dependencies.&lt;/p&gt;&lt;p&gt;The observant, will notice that what we&amp;#8217;re trying to pass in as a dependency is an interface, and as you know, an interface cannot be instantiated. This is where it gets cool and we actually already did the same thing in our tests. In our tests however, we used &lt;code&gt;App::instance()&lt;/code&gt; to provide an already created instance instead of the interface. For our Controllers, we&amp;#8217;re actually going to tell Laravel that whenever an instance of &lt;code&gt;PostRepositoryInterface&lt;/code&gt; is requested, to actually return an instance of &lt;code&gt;EloquentPostRepository&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Open up your &lt;code&gt;app/routes.php&lt;/code&gt; file and add the following to the top of the file&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;App::bind('PostRepositoryInterface', 'EloquentPostRepository');
App::bind('CommentRepositoryInterface', 'EloquentCommentRepository');
&lt;/pre&gt;&lt;p&gt;After adding those lines, anytime &lt;code&gt;App::make()&lt;/code&gt; asks for an instance of &lt;code&gt;PostRepositoryInterface&lt;/code&gt;, it will create an instance of &lt;code&gt;EloquentPostRepository&lt;/code&gt;, which is assumed to implement &lt;code&gt;PostRepositoryInterface&lt;/code&gt;. If you were to ever change your repository to instead use a different ORM than Eloquent, or maybe a file-based driver, all you have to do is change these two lines and you&amp;#8217;re good to go, your Controllers will still work as normal. The Controllers actual dependency is any object that implements that interface and we can determine at run-time what that implementation actually is.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;PostRepositoryInterface&lt;/code&gt; and &lt;code&gt;CommentRepositoryInterface&lt;/code&gt; must actually exist and the bindings must actually implement them. So let&amp;#39;s create them now:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/repositories/PostRepositoryInterface.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

interface PostRepositoryInterface {
  public function findById($id);
  public function findAll();
  public function paginate($limit = null);
  public function store($data);
  public function update($id, $data);
  public function destroy($id);
  public function validate($data);
  public function instance();
}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/repositories/CommentRepositoryInterface.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

interface CommentRepositoryInterface {
  public function findById($post_id, $id);
  public function findAll($post_id);
  public function store($post_id, $data);
  public function update($post_id, $id, $data);
  public function destroy($post_id, $id);
  public function validate($data);
  public function instance();
}
&lt;/pre&gt;&lt;p&gt;Now that we have our two interfaces built, we must provide implementations of these interfaces. Let&amp;#39;s build them now.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/repositories/EloquentPostRepository.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;As the name of this implementation implies, we&amp;#8217;re relying on Eloquent, which we can call directly. If you had other dependencies, remember that &lt;code&gt;App::make()&lt;/code&gt; is being used to resolve this repository, so you can feel free to use the same constructor method we used with our Controllers to inject your dependencies.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class EloquentPostRepository implements PostRepositoryInterface {

  public function findById($id)
  {
    $post = Post::with(array(
        'comments' =&amp;gt; function($q)
        {
          $q-&amp;gt;orderBy('created_at', 'desc');
        }
      ))
      -&amp;gt;where('id', $id)
      -&amp;gt;first();

    if(!$post) throw new NotFoundException('Post Not Found');
    return $post;
  }

  public function findAll()
  {
    return Post::with(array(
        'comments' =&amp;gt; function($q)
        {
          $q-&amp;gt;orderBy('created_at', 'desc');
        }
      ))
      -&amp;gt;orderBy('created_at', 'desc')
      -&amp;gt;get();
  }

  public function paginate($limit = null)
  {
    return Post::paginate($limit);
  }

  public function store($data)
  {
    $this-&amp;gt;validate($data);
    return Post::create($data);
  }

  public function update($id, $data)
  {
    $post = $this-&amp;gt;findById($id);
    $post-&amp;gt;fill($data);
    $this-&amp;gt;validate($post-&amp;gt;toArray());
    $post-&amp;gt;save();
    return $post;
  }

  public function destroy($id)
  {
    $post = $this-&amp;gt;findById($id);
    $post-&amp;gt;delete();
    return true;
  }

  public function validate($data)
  {
    $validator = Validator::make($data, Post::$rules);
    if($validator-&amp;gt;fails()) throw new ValidationException($validator);
    return true;
  }

  public function instance($data = array())
  {
    return new Post($data);
  }

}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/repositories/EloquentCommentRepository.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class EloquentCommentRepository implements CommentRepositoryInterface {

  public function findById($post_id, $id)
  {
    $comment = Comment::find($id);
    if(!$comment || $comment-&amp;gt;post_id != $post_id) throw new NotFoundException('Comment Not Found');
    return $comment;
  }

  public function findAll($post_id)
  {
    return Comment::where('post_id', $post_id)
      -&amp;gt;orderBy('created_at', 'desc')
      -&amp;gt;get();
  }

  public function store($post_id, $data)
  {
    $data['post_id'] = $post_id;
    $this-&amp;gt;validate($data);
    return Comment::create($data);
  }

  public function update($post_id, $id, $data)
  {
    $comment = $this-&amp;gt;findById($post_id, $id);
    $comment-&amp;gt;fill($data);
    $this-&amp;gt;validate($comment-&amp;gt;toArray());
    $comment-&amp;gt;save();
    return $comment;
  }

  public function destroy($post_id, $id)
  {
    $comment = $this-&amp;gt;findById($post_id, $id);
    $comment-&amp;gt;delete();
    return true;
  }

  public function validate($data)
  {
    $validator = Validator::make($data, Comment::$rules);
    if($validator-&amp;gt;fails()) throw new ValidationException($validator);
    return true;
  }

  public function instance($data = array())
  {
    return new Comment($data);
  }

}
&lt;/pre&gt;&lt;p&gt;If you take a look in our repositories, there are a few Exceptions that we are throwing, which are not native, nor do they belong to Laravel. Those are custom Exceptions that we&amp;#8217;re using to simplify our code. By using custom Exceptions, we&amp;#8217;re able to easily halt the progress of the application if certain conditions are met. For instance, if a post is not found, we can just toss a NotFoundException, and the application will handle it accordingly, but, not by showing a 500 error as usual, instead we&amp;#8217;re going to setup custom error handlers. You could alternatively use &lt;code&gt;App::abort(404)&lt;/code&gt; or something along those lines, but I find that this method saves me many conditional statements and repeat code, as well as allowing me to adjust the implementation of error reporting in a single place very easily.&lt;/p&gt;&lt;p&gt;First let&amp;#39;s define the custom Exceptions. Create a file in your &lt;code&gt;app&lt;/code&gt; folder called &lt;code&gt;errors.php&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;touch app/errors.php
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/errors.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class PermissionException extends Exception {

  public function __construct($message = null, $code = 403)
  {
    parent::__construct($message ?: 'Action not allowed', $code);
  }

}

class ValidationException extends Exception {

  protected $messages;

  /**
   * We are adjusting this constructor to receive an instance
   * of the validator as opposed to a string to save us some typing
   * @param Validator $validator failed validator object
   */
  public function __construct($validator)
  {
    $this-&amp;gt;messages = $validator-&amp;gt;messages();
    parent::__construct($this-&amp;gt;messages, 400);
  }

  public function getMessages()
  {
    return $this-&amp;gt;messages;
  }

}

class NotFoundException extends Exception {

  public function __construct($message = null, $code = 404)
  {
    parent::__construct($message ?: 'Resource Not Found', $code);
  }

}
&lt;/pre&gt;&lt;p&gt;These are very simple Exceptions, notice for the ValidationException, we can just pass it the failed validator instance and it will handle the error messages accordingly!&lt;/p&gt;&lt;p&gt;Now we need to define our error handlers that will be called when one of these Exceptions are thrown. These are basically Event listeners, whenever one of these exceptions are thrown, it&amp;#8217;s treated as an Event and calls the appropriate function. It&amp;#8217;s very simple to add logging or any other error handling procedures here.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/filters.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;...

/**
 * General HttpException handler
 */
App::error( function(Symfony\Component\HttpKernel\Exception\HttpException $e, $code)
{
  $headers = $e-&amp;gt;getHeaders();

  switch($code)
  {
    case 401:
      $default_message = 'Invalid API key';
      $headers['WWW-Authenticate'] = 'Basic realm=&amp;quot;CRM REST API&amp;quot;';
    break;

    case 403:
      $default_message = 'Insufficient privileges to perform this action';
    break;

    case 404:
      $default_message = 'The requested resource was not found';
    break;

    default:
      $default_message = 'An error was encountered';
  }

  return Response::json(array(
    'error' =&amp;gt; $e-&amp;gt;getMessage() ?: $default_message
  ), $code, $headers);
});

/**
 * Permission Exception Handler
 */
App::error(function(PermissionException $e, $code)
{
  return Response::json($e-&amp;gt;getMessage(), $e-&amp;gt;getCode());
});

/**
 * Validation Exception Handler
 */
App::error(function(ValidationException $e, $code)
{
  return Response::json($e-&amp;gt;getMessages(), $code);
});

/**
 * Not Found Exception Handler
 */
App::error(function(NotFoundException $e)
{
  return Response::json($e-&amp;gt;getMessage(), $e-&amp;gt;getCode());
});
&lt;/pre&gt;&lt;p&gt;We now need to let our auto-loader know about these new files. So we must tell Composer where to check for them:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;composer.json&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Notice that we added the &lt;code&gt;&amp;quot;app/errors.php&amp;quot;&lt;/code&gt; line.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;{
  &amp;quot;require&amp;quot;: {
    &amp;quot;laravel/framework&amp;quot;: &amp;quot;4.0.*&amp;quot;,
    &amp;quot;way/generators&amp;quot;: &amp;quot;dev-master&amp;quot;,
    &amp;quot;twitter/bootstrap&amp;quot;: &amp;quot;dev-master&amp;quot;,
    &amp;quot;conarwelsh/mustache-l4&amp;quot;: &amp;quot;dev-master&amp;quot;
  },
  &amp;quot;require-dev&amp;quot;: {
    &amp;quot;phpunit/phpunit&amp;quot;: &amp;quot;3.7.*&amp;quot;,
    &amp;quot;mockery/mockery&amp;quot;: &amp;quot;0.7.*&amp;quot;
  },
  &amp;quot;autoload&amp;quot;: {
    &amp;quot;classmap&amp;quot;: [
      &amp;quot;app/commands&amp;quot;,
      &amp;quot;app/controllers&amp;quot;,
      &amp;quot;app/models&amp;quot;,
      &amp;quot;app/database/migrations&amp;quot;,
      &amp;quot;app/database/seeds&amp;quot;,
      &amp;quot;app/tests/TestCase.php&amp;quot;,
      &amp;quot;app/repositories&amp;quot;,
      &amp;quot;app/errors.php&amp;quot;
    ]
  },
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;post-update-cmd&amp;quot;: &amp;quot;php artisan optimize&amp;quot;
  },
  &amp;quot;minimum-stability&amp;quot;: &amp;quot;dev&amp;quot;
}
&lt;/pre&gt;&lt;p&gt;We must now tell Composer to actually check for these files and include them in the auto-load registry.&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;composer dump-autoload
&lt;/pre&gt;&lt;p&gt;Great, so we have completed our controllers and our repositories, the last two items in our MVRC that we have to take care of is the models and views, both of which are pretty straight forward.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/models/Post.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php
/**
 * Represent a Post Item, or Collection
 */
class Post extends Eloquent {

  /**
   * Items that are &amp;quot;fillable&amp;quot;
   * meaning we can mass-assign them from the constructor
   * or $post-&amp;gt;fill()
   * @var array
   */
  protected $fillable = array(
    'title', 'content', 'author_name'
  );

  /**
   * Validation Rules
   * this is just a place for us to store these, you could
   * alternatively place them in your repository
   * @var array
   */
  public static $rules = array(
    'title'    =&amp;gt; 'required',
    'author_name' =&amp;gt; 'required'
  );

  /**
   * Define the relationship with the comments table
   * @return Collection collection of Comment Models
   */
  public function comments()
  {
    return $this-&amp;gt;hasMany('Comment');
  }

}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/models/Comment.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php
/**
 * Represent a Comment Item, or Collection
 */
class Comment extends Eloquent {

  /**
   * Items that are &amp;quot;fillable&amp;quot;
   * meaning we can mass-assign them from the constructor
   * or $comment-&amp;gt;fill()
   * @var array
   */
  protected $fillable = array(
    'post_id', 'content', 'author_name'
  );

  /**
   * Validation Rules
   * this is just a place for us to store these, you could
   * alternatively place them in your repository
   * @var array
   */
  public static $rules = array(
    'post_id'   =&amp;gt; 'required|numeric',
    'content'   =&amp;gt; 'required',
    'author_name' =&amp;gt; 'required'
  );

  /**
   * Define the relationship with the posts table
   * @return Model parent Post model
   */
  public function post()
  {
    return $this-&amp;gt;belongsTo('Post');
  }

}
&lt;/pre&gt;&lt;p&gt;As far as views are concerned, I&amp;#8217;m just going to mark up some simple bootstrap-friendly pages. Remember to change each files extension to &lt;code&gt;.mustache&lt;/code&gt; though, since our generator thought that we would be using &lt;code&gt;.blade.php&lt;/code&gt;. We&amp;#8217;re also going to create a few &amp;quot;partial&amp;quot; views using the Rails convention of prefixing them with an &lt;code&gt;_&lt;/code&gt; to signify a partial.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note: I skipped a few views, as we will not be using them in this tutorial.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;public/views/posts/index.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;For the &lt;code&gt;index&lt;/code&gt; page view we&amp;#8217;ll just loop over all of our posts, showing the post partial for each.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;{{#posts}}
  {{&amp;gt; posts._post}}
{{/posts}}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;public/views/posts/show.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;For the &lt;code&gt;show&lt;/code&gt; view we&amp;#8217;ll show an entire post and its comments:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;article&amp;gt;
  &amp;lt;h3&amp;gt;
    {{ post.title }} {{ post.id }}
    &amp;lt;small&amp;gt;{{ post.author_name }}&amp;lt;/small&amp;gt;
  &amp;lt;/h3&amp;gt;
  &amp;lt;div&amp;gt;
    {{ post.content }}
  &amp;lt;/div&amp;gt;
&amp;lt;/article&amp;gt;

&amp;lt;div&amp;gt;
  &amp;lt;h2&amp;gt;Add A Comment&amp;lt;/h2&amp;gt;
  {{&amp;gt; comments._form }}

  &amp;lt;section data-role=&amp;quot;comments&amp;quot;&amp;gt;
    {{#post.comments}}
      &amp;lt;div&amp;gt;
        {{&amp;gt; comments._comment }}
      &amp;lt;/div&amp;gt;
    {{/post.comments}}
  &amp;lt;/section&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;public/views/posts/_post.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s the partial that we&amp;#8217;ll use to show a &lt;code&gt;post&lt;/code&gt; in a list. This is used on our &lt;code&gt;index&lt;/code&gt; view.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;article data-toggle=&amp;quot;view&amp;quot; data-target=&amp;quot;posts/{{ id }}&amp;quot;&amp;gt;
  &amp;lt;h3&amp;gt;{{ title }} {{ id }}&amp;lt;/h3&amp;gt;
  &amp;lt;cite&amp;gt;{{ author_name }} on {{ created_at }}&amp;lt;/cite&amp;gt;
&amp;lt;/article&amp;gt;
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;public/views/posts/_form.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s the &lt;code&gt;form&lt;/code&gt; partial needed to create a post, we&amp;#8217;ll use this from our API, but this could also be a useful view in an admin panel and other places, which is why we choose to make it a partial.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;{{#exists}}
  &amp;lt;form action=&amp;quot;/v1/posts/{{ post.id }}&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
    &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;_method&amp;quot; value=&amp;quot;PUT&amp;quot; /&amp;gt;
{{/exists}}
{{^exists}}
  &amp;lt;form action=&amp;quot;/v1/posts&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
{{/exists}}

  &amp;lt;fieldset&amp;gt;

    &amp;lt;div class=&amp;quot;control-group&amp;quot;&amp;gt;
      &amp;lt;label class=&amp;quot;control-label&amp;quot;&amp;gt;&amp;lt;/label&amp;gt;
      &amp;lt;div class=&amp;quot;controls&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;title&amp;quot; value=&amp;quot;{{ post.title }}&amp;quot; /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class=&amp;quot;control-group&amp;quot;&amp;gt;
      &amp;lt;label class=&amp;quot;control-label&amp;quot;&amp;gt;&amp;lt;/label&amp;gt;
      &amp;lt;div class=&amp;quot;controls&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;author_name&amp;quot; value=&amp;quot;{{ post.author_name }}&amp;quot; /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class=&amp;quot;control-group&amp;quot;&amp;gt;
      &amp;lt;label class=&amp;quot;control-label&amp;quot;&amp;gt;&amp;lt;/label&amp;gt;
      &amp;lt;div class=&amp;quot;controls&amp;quot;&amp;gt;
        &amp;lt;textarea name=&amp;quot;content&amp;quot;&amp;gt;{{ post.content }}&amp;quot;&amp;lt;/textarea&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class=&amp;quot;form-actions&amp;quot;&amp;gt;
      &amp;lt;input type=&amp;quot;submit&amp;quot; class=&amp;quot;btn btn-primary&amp;quot; value=&amp;quot;Save&amp;quot; /&amp;gt;
    &amp;lt;/div&amp;gt;

  &amp;lt;/fieldset&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;public/views/comments/_comment.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s the &lt;code&gt;comment&lt;/code&gt; partial which is used to represent a single comment in a list of comments:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;h5&amp;gt;
  {{ author_name }}
  &amp;lt;small&amp;gt;{{ created_at }}&amp;lt;/small&amp;gt;
&amp;lt;/h5&amp;gt;
&amp;lt;div&amp;gt;
  {{ content }}
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;public/views/comments/_form.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The form needed to create a comment &amp;#8211; both used in the API and the Show Post view:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;{{#exists}}
  &amp;lt;form class=&amp;quot;form-horizontal&amp;quot; action=&amp;quot;/v1/posts/{{ comment.post_id }}/{{ id }}&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
    &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;_method&amp;quot; value=&amp;quot;PUT&amp;quot; /&amp;gt;
{{/exists}}
{{^exists}}
  &amp;lt;form class=&amp;quot;form-horizontal&amp;quot; action=&amp;quot;/v1/posts/{{ comment.post_id }}&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
{{/exists}}

  &amp;lt;fieldset&amp;gt;

    &amp;lt;div class=&amp;quot;control-group&amp;quot;&amp;gt;
      &amp;lt;label class=&amp;quot;control-label&amp;quot;&amp;gt;Author Name&amp;lt;/label&amp;gt;
      &amp;lt;div class=&amp;quot;controls&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;author_name&amp;quot; value=&amp;quot;{{ comment.author_name }}&amp;quot; /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class=&amp;quot;control-group&amp;quot;&amp;gt;
      &amp;lt;label class=&amp;quot;control-label&amp;quot;&amp;gt;Comment&amp;lt;/label&amp;gt;
      &amp;lt;div class=&amp;quot;controls&amp;quot;&amp;gt;
        &amp;lt;textarea name=&amp;quot;content&amp;quot;&amp;gt;{{ comment.content }}&amp;lt;/textarea&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class=&amp;quot;form-actions&amp;quot;&amp;gt;
      &amp;lt;input type=&amp;quot;submit&amp;quot; class=&amp;quot;btn btn-primary&amp;quot; value=&amp;quot;Save&amp;quot; /&amp;gt;
    &amp;lt;/div&amp;gt;

  &amp;lt;/fieldset&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;public/views/layouts/_notification.mustache&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;And here&amp;#8217;s the helper view partial to allow us to show a notification:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;div class=&amp;quot;alert alert-{{type}}&amp;quot;&amp;gt;
  {{message}}
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;Great, we have all of our API components in place. Let&amp;#39;s run our unit tests to see where we&amp;#8217;re at!&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;vendor/phpunit/phpunit/phpunit.php
&lt;/pre&gt;&lt;p&gt;Your first run of this test should pass with flying (green) colors. However, if you were to run this test again, you&amp;#8217;ll notice that it fails now with a handful of errors, and that is because our repository tests actually tested the database, and in doing so deleted some of the records our previous tests used to assert values. This is an easy fix, all we have to do is tell our tests that they need to re-seed the database after each test. In addition, we did not receive a noticable error for this, but we did not close Mockery after each test either, this is a requirement of Mockery that you can find in their docs. So let&amp;#39;s add both missing methods.&lt;/p&gt;&lt;p&gt;Open up &lt;code&gt;app/tests/TestCase.php&lt;/code&gt; and add the following two methods:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;/**
 * setUp is called prior to each test
 */
public function setUp()
{
  parent::setUp();
  $this-&amp;gt;seed();
}

/**
 * tearDown is called after each test
 * @return [type] [description]
 */
public function tearDown()
{
  Mockery::close();
}
&lt;/pre&gt;&lt;p&gt;This is great, we now said that at every &amp;quot;setUp&amp;quot;, which is run before each test, to re-seed the database. However we still have one problem, everytime you re-seed, it&amp;#8217;s only going to append new rows to the tables. Our tests are looking for items with a row ID of one, so we still have a few changes to make. We just need to tell the database to truncate our tables when seeding:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/database/seeds/CommentsTableSeeder.php&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Before we insert the new rows, we&amp;#8217;ll truncate the table, deleting all rows and resetting the auto-increment counter.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class CommentsTableSeeder extends Seeder {

  public function run()
  {
    $comments = array(
      array(
        'content'   =&amp;gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',
        'author_name' =&amp;gt; 'Testy McTesterson',
        'post_id'   =&amp;gt; 1,
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
      array(
        'content'   =&amp;gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',
        'author_name' =&amp;gt; 'Testy McTesterson',
        'post_id'   =&amp;gt; 1,
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
      array(
        'content'   =&amp;gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',
        'author_name' =&amp;gt; 'Testy McTesterson',
        'post_id'   =&amp;gt; 2,
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
    );

    //truncate the comments table when we seed
    DB::table('comments')-&amp;gt;truncate();
    DB::table('comments')-&amp;gt;insert($comments);
  }

}
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;app/database/seeds/PostsTableSeeder.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

class PostsTableSeeder extends Seeder {

  public function run()
  {
    $posts = array(
      array(
        'title'    =&amp;gt; 'Test Post',
        'content'   =&amp;gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',
        'author_name' =&amp;gt; 'Conar Welsh',
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      ),
      array(
        'title'    =&amp;gt; 'Another Test Post',
        'content'   =&amp;gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',
        'author_name' =&amp;gt; 'Conar Welsh',
        'created_at' =&amp;gt; date('Y-m-d H:i:s'),
        'updated_at' =&amp;gt; date('Y-m-d H:i:s'),
      )
    );

    //truncate the posts table each time we seed
    DB::table('posts')-&amp;gt;truncate();
    DB::table('posts')-&amp;gt;insert($posts);
  }

}
&lt;/pre&gt;&lt;p&gt;Now you should be able to run the tests any number of times and get passing tests each time! That means we have fulfilled our TDD cycle and we&amp;#8217;re not allowed to write anymore production code for our API!! Let&amp;#39;s just commit our changes to our repo and move onto the Backbone application!&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;git add . &amp;amp;&amp;amp; git commit -am &amp;quot;built out the API and corresponding tests&amp;quot;
&lt;/pre&gt;&lt;hr
/&gt;&lt;h2&gt;Backbone App&lt;/h2&gt;&lt;p&gt;Now that we have completed all of the back-end work, we can move forward to creating a nice user interface to access all of that data. We&amp;#8217;ll keep this part of the project a little bit on the simpler side, and I warn you that my approach can be considered an opinionated one. I have seen many people with so many different methods for structuring a Backbone application. My trials and errors have led me to my current method, if you do not agree with it, my hope is that it may inspire you to find your own!&lt;/p&gt;&lt;p&gt;We&amp;#8217;re going to use the Mustache templating engine instead of Underscore, this will allow us to share our views between the client and server! The trick is in how you load the views, we&amp;#8217;re going to use AJAX in this tutorial, but it&amp;#8217;s just as easy to load them all into the main template, or precompile them.&lt;/p&gt;&lt;h3&gt;Router&lt;/h3&gt;&lt;p&gt;First we&amp;#8217;ll get our router going. There are two parts to this, the Laravel router, and the Backbone router.&lt;/p&gt;&lt;h4&gt;Laravel Router&lt;/h4&gt;&lt;p&gt;There are two main approaches we can take here:&lt;/p&gt;&lt;h5&gt;Approach #1: The catch-all&lt;/h5&gt;&lt;p&gt;Remember I told you when you were adding the resource routes that it was important that you placed them ABOVE the app route?? The catch-all method is the reason for that statement. The overall goal of this method is to have any routes that have not found a match in Laravel, be caught and sent to Backbone. Implementing this method is easy:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;app/routes.php&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;// change your existing app route to this:
// we are basically just giving it an optional parameter of &amp;quot;anything&amp;quot;
Route::get('/{path?}', function($path = null)
{
  return View::make('app');
})
-&amp;gt;where('path', '.*'); //regex to match anything (dots, slashes, letters, numbers, etc)
&lt;/pre&gt;&lt;p&gt;Now, every route other than our API routes will render our app view.&lt;/p&gt;&lt;p&gt;In addition, if you have a multi-page app (several single page apps), you can define several of these catch-alls:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;Route::get('someApp1{path?}', function($path = null)
{
  return View::make('app');
})
-&amp;gt;where('path', '.*');

Route::get('anotherApp/{path?}', function($path = null)
{
  return View::make('app');
})
-&amp;gt;where('path', '.*');

Route::get('athirdapp{path?}', function($path = null)
{
  return View::make('app');
})
-&amp;gt;where('path', '.*');
&lt;/pre&gt;&lt;blockquote&gt;&lt;p&gt;Note: Keep in mind the &amp;#39;/&amp;#39; before {path?}. If that slash is there, it&amp;#8217;ll be required in the URL (with the exception of the index route), sometimes this is desired and sometimes not.&lt;/p&gt;&lt;/blockquote&gt;&lt;h5&gt;Approach #2:&lt;/h5&gt;&lt;p&gt;Since our front and back end share views&amp;#8230; wouldn&amp;#39;t it be extremely easy to just define routes in both places? You can even do this &lt;em&gt;in addition&lt;/em&gt; to the catch-all approach if you want.&lt;/p&gt;&lt;p&gt;The routes that we&amp;#8217;re going to end up defining for the app are simply:&lt;/p&gt;&lt;pre class="brush: plain; title: ; notranslate"&gt;GET /
GET /posts/:id
&lt;/pre&gt;&lt;p&gt;app/routes.php&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;&amp;lt;?php

App::bind('PostRepositoryInterface', 'EloquentPostRepository'); 
App::bind('CommentRepositoryInterface', 'EloquentCommentRepository');
//create a group of routes that will belong to APIv1
Route::group(array('prefix' =&amp;gt; 'v1'), function()
{
  Route::resource('posts', 'V1\PostsController');
  Route::resource('posts.comments', 'V1\PostsCommentsController');
});
/**
 * Method #1: use catch-all
 * optionally commented out while we use Method 2
 */
// change your existing app route to this:
// we are basically just giving it an optional parameter of &amp;quot;anything&amp;quot;
// Route::get('/{path?}', function($path = null)
// {
//   return View::make('layouts.application')-&amp;gt;nest('content', 'app');
// })
// -&amp;gt;where('path', '.*'); //regex to match anything (dots, slashes, letters, numbers, etc)
/**
 * Method #2: define each route
 */
Route::get('/', function()
{
  $posts = App::make('PostRepositoryInterface')-&amp;gt;paginate();
  return View::make('layouts.application')-&amp;gt;nest('content', 'posts.index', array(
    'posts' =&amp;gt; $posts
  ));
});

Route::get('posts/{id}', function($id)
{
  $post = App::make('PostRepositoryInterface')-&amp;gt;findById($id);
  return View::make('layouts.application')-&amp;gt;nest('content', 'posts.show', array(
    'post' =&amp;gt; $post
  ));
});
&lt;/pre&gt;&lt;p&gt;Pretty cool huh?! Regardless of which method we use, or the combination of both, your Backbone router will end up mostly the same.&lt;/p&gt;&lt;p&gt;Notice that we&amp;#8217;re using our Repository again, this is yet another reason why Repositories are a useful addition to our framework. We can now run almost all of the logic that the controller does, but without repeating hardly any of the code!&lt;/p&gt;&lt;p&gt;Keep in mind a few things while choosing which method to use, if you use the catch-all, it will do just like the name implies&amp;#8230; catch-&lt;em&gt;ALL&lt;/em&gt;. This means there is no such thing as a 404 on your site anymore. No matter the request, its landing on the app page (unless you manually toss an exception somewhere such as your repository). The inverse is, with defining each route, now you have two sets of routes to manage. Both methods have their ups and downs, but both are equally easy to deal with.&lt;/p&gt;&lt;h3&gt;Base View&lt;/h3&gt;&lt;p&gt;One view to rule them all! This &lt;code&gt;BaseView&lt;/code&gt; is the view that all of our other Views will inherit from. For our purposes, this view has but one job&amp;#8230; templating! In a larger app this view is a good place to put other shared logic.&lt;/p&gt;&lt;p&gt;We&amp;#8217;ll simply extend &lt;code&gt;Backbone.View&lt;/code&gt; and add a &lt;code&gt;template&lt;/code&gt; function that will return our view from the cache if it exists, or get it via AJAX and place it in the cache. We have to use synchronous AJAX due to the way that Mustache.js fetches partials, but since we&amp;#8217;re only retrieving these views if they are not cached, we shouldn&amp;#8217;t receive much of a performance hit here.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;/**
 ***************************************
 * Array Storage Driver
 * used to store our views
 ***************************************
 */
var ArrayStorage = function(){
  this.storage = {};
};
ArrayStorage.prototype.get = function(key)
{
  return this.storage[key];
};
ArrayStorage.prototype.set = function(key, val)
{
  return this.storage[key] = val;
};
/**
 ***************************************
 * Base View
 ***************************************
 */
var BaseView = bb.View.extend({

  /**
   * Set our storage driver
   */
  templateDriver: new ArrayStorage,

  /**
   * Set the base path for where our views are located
   */
  viewPath: '/views/',

  /**
   * Get the template, and apply the variables
   */
  template: function()
  {
    var view, data, template, self;

    switch(arguments.length)
    {
      case 1:
        view = this.view;
        data = arguments[0];
        break;
      case 2:
        view = arguments[0];
        data = arguments[1];
        break;
    }

    template = this.getTemplate(view, false);
    self = this;

    return template(data, function(partial)
    {
      return self.getTemplate(partial, true);
    });
  },

  /**
   * Facade that will help us abstract our storage engine,
   * should we ever want to swap to something like LocalStorage
   */
  getTemplate: function(view, isPartial)
  {
    return this.templateDriver.get(view) || this.fetch(view, isPartial);
  },

  /**
   * Facade that will help us abstract our storage engine,
   * should we ever want to swap to something like LocalStorage
   */
  setTemplate: function(name, template)
  {
    return this.templateDriver.set(name, template);
  },

  /**
   * Function to retrieve the template via ajax
   */
  fetch: function(view, isPartial)
  {
    var markup = $.ajax({
      async: false,

      //the URL of our template, we can optionally use dot notation
      url: this.viewPath + view.split('.').join('/') + '.mustache'
    }).responseText;

    return isPartial
      ? markup
      : this.setTemplate(view, Mustache.compile(markup));
  }
});
&lt;/pre&gt;&lt;h3&gt;PostView&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;PostView&lt;/code&gt; renders a single blog post:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// this view will show an entire post
// comment form, and comments
var PostView = BaseView.extend({

  //the location of the template this view will use, we can use dot notation
  view: 'posts.show',

  //events this view should subscribe to
  events: {
    'submit form': function(e)
    {
      e.preventDefault();
      e.stopPropagation();

      return this.addComment( $(e.target).serialize() );
    }
  },

  //render our view into the defined `el`
  render: function()
  {
    var self = this;

    self.$el.html( this.template({
      post: this.model.attributes
    }) );
  },

  //add a comment for this post
  addComment: function(formData)
  {
    var
      self = this,

      //build our url
      action = this.model.url() + '/comments'
    ;

    //submit a post to our api
    $.post(action, formData, function(comment, status, xhr)
    {
      //create a new comment partial
      var view = new CommentViewPartial({
        //we are using a blank backbone model, since we done have any specific logic needed
        model: new bb.Model(comment)
      });

      //prepend the comment partial to the comments list
      view.render().$el.prependTo(self.$('[data-role=&amp;quot;comments&amp;quot;]'));

      //reset the form
      self.$('input[type=&amp;quot;text&amp;quot;], textarea').val('');

      //prepend our new comment to the collection
      self.model.attributes.comments.unshift(comment);

      //send a notification that we successfully added the comment
      notifications.add({
        type: 'success',
        message: 'Comment Added!'
      });
    });

  }
});
&lt;/pre&gt;&lt;h3&gt;Partial Views&lt;/h3&gt;&lt;p&gt;We&amp;#8217;ll need a few views to render partials. We mainly just need to tell the view which template to use and that it should extend our view that provides the method to fetch our template.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// this will be used for rendering a single comment in a list
var CommentViewPartial = BaseView.extend({
  //define our template location
  view: 'comments._comment',
  render: function()
  {
    this.$el.html( this.template(this.model.attributes) );
    return this;
  }
});

//this view will be used for rendering a single post in a list
var PostViewPartial = BaseView.extend({
  //define our template location
  view: 'posts._post',
  render: function()
  {
    this.$el.html( this.template(this.model.attributes) );
    return this;
  }
});
&lt;/pre&gt;&lt;h3&gt;Blog View&lt;/h3&gt;&lt;p&gt;This is our overall application view. It contains our configuration logic, as well as handling the fetching of our &lt;code&gt;PostCollection&lt;/code&gt;. We also setup a cool little infinite scroll feature. Notice how we&amp;#8217;re using jQuery promises to ensure that the fetching of our collection has completed prior to rendering the view.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;var Blog = BaseView.extend({
  //define our template location
  view: 'posts.index',

  //setup our app configuration
  initialize: function()
  {
    this.perPage = this.options.perPage || 15;
    this.page   = this.options.page || 0;
    this.fetching = this.collection.fetch();

    if(this.options.infiniteScroll) this.enableInfiniteScroll();
  },

  //wait til the collection has been fetched, and render the view
  render: function()
  {
    var self = this;
    this.fetching.done(function()
    {
      self.$el.html('');
      self.addPosts();

      // var posts = this.paginate()

      // for(var i=0; i&amp;lt;posts.length; i++)
      // {
      //   posts[i] = posts[i].toJSON();
      // }

      // self.$el.html( self.template({
      //   posts: posts
      // }) );

      if(self.options.infiniteScroll) self.enableInfiniteScroll();
    });
  },

  //helper function to limit the amount of posts we show at a time
  paginate: function()
  {
    var posts;
    posts = this.collection.rest(this.perPage * this.page);
    posts = _.first(posts, this.perPage);
    this.page++;

    return posts;
  },

  //add the next set of posts to the view
  addPosts: function()
  {
    var posts = this.paginate();

    for(var i=0; i&amp;lt;posts.length; i++)
    {
      this.addOnePost( posts[i] );
    }
  },

  //helper function to add a single post to the view
  addOnePost: function(model)
  {
    var view = new PostViewPartial({
      model: model
    });
    this.$el.append( view.render().el );
  },

  //this function will show an entire post, we could alternatively make this its own View
  //however I personally like having it available in the overall application view, as it
  //makes it easier to manage the state
  showPost: function(id)
  {
    var self = this;

    this.disableInifiniteScroll();

    this.fetching.done(function()
    {
      var model = self.collection.get(id);

      if(!self.postView)
      {
        self.postView = new self.options.postView({
          el: self.el
        });
      }
      self.postView.model = model;
      self.postView.render();
    });
  },

  //function to run during the onScroll event
  infiniteScroll: function()
  {
    if($window.scrollTop() &amp;gt;= $document.height() - $window.height() - 50)
    {
      this.addPosts();
    }
  },

  //listen for the onScoll event
  enableInfiniteScroll: function()
  {
    var self = this;

    $window.on('scroll', function()
    {
      self.infiniteScroll();
    });
  },

  //stop listening to the onScroll event
  disableInifiniteScroll: function()
  {
    $window.off('scroll');
  }
});
&lt;/pre&gt;&lt;h3&gt;PostCollection&lt;/h3&gt;&lt;p&gt;Setup our &lt;code&gt;PostCollection&lt;/code&gt; &amp;#8211; we just need to tell the Collection the URL it should use to fetch its contents.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;// the posts collection is configured to fetch
// from our API, as well as use our PostModel
var PostCollection = bb.Collection.extend({
  url: '/v1/posts'
});
&lt;/pre&gt;&lt;h3&gt;Blog Router&lt;/h3&gt;&lt;p&gt;Notice that we&amp;#8217;re not instantiating new instances of our views, we&amp;#8217;re merely telling them to render. Our initialize functions are designed to only be ran once, as we don&amp;#8217;t want them to run but once, on page load.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;var BlogRouter = bb.Router.extend({
  routes: {
    &amp;quot;&amp;quot;: &amp;quot;index&amp;quot;,
    &amp;quot;posts/:id&amp;quot;: &amp;quot;show&amp;quot;
  },
  initialize: function(options)
  {
    // i do this to avoid having to hardcode an instance of a view
    // when we instantiate the router we will pass in the view instance
    this.blog = options.blog;
  },
  index: function()
  {
    //reset the paginator
    this.blog.page = 0;

    //render the post list
    this.blog.render();
  },
  show: function(id)
  {
    //render the full-post view
    this.blog.showPost(id);
  }
});
&lt;/pre&gt;&lt;h3&gt;Notifications Collection&lt;/h3&gt;&lt;p&gt;We&amp;#8217;re just going to setup a simple Collection to store user notifications:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;var notifications = new bb.Collection();
&lt;/pre&gt;&lt;h3&gt;NotificationsView&lt;/h3&gt;&lt;p&gt;This view will handle the displaying and hiding of user notifications:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;var NotificationView = BaseView.extend({
  el: $('#notifications'),
  view: 'layouts._notification',
  initialize: function()
  {
    this.listenTo(notifications, 'add', this.render);
  },
  render: function(notification)
  {
    var $message = $( this.template(notification.toJSON()) );
    this.$el.append($message);
    this.delayedHide($message);
  },
  delayedHide: function($message)
  {
    var timeout = setTimeout(function()
    {
      $message.fadeOut(function()
      {
        $message.remove();
      });
    }, 5*1000);

    var self = this;
    $message.hover(
      function()
      {
        timeout = clearTimeout(timeout);
      },
      function()
      {
        self.delayedHide($message);
      }
    );
  }
});
var notificationView = new NotificationView();
&lt;/pre&gt;&lt;h3&gt;Error Handling&lt;/h3&gt;&lt;p&gt;Since we used the custom exception handlers for our API, it makes it very easy to handle any error our API may throw. Very similar to the way we defined our event listeners for our API in the &lt;code&gt;app/filters.php&lt;/code&gt; file, we&amp;#8217;ll define event listeners for our app here. Each code that could be thrown can just show a notification very easily!&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;$.ajaxSetup({
  statusCode: {
    401: function()
    {
      notification.add({
        type: null, //error, success, info, null
        message: 'You do not have permission to do that'
      });
    },
    403: function()
    {
      notification.add({
        type: null, //error, success, info, null
        message: 'You do not have permission to do that'
      });
    },
    404: function()
    {
      notification.add({
        type: 'error', //error, success, info, null
        message: '404: Page Not Found'
      });
    },
    500: function()
    {
      notification.add({
        type: 'error', //error, success, info, null
        message: 'The server encountered an error'
      });
    }
  }
});
&lt;/pre&gt;&lt;hr
/&gt;&lt;h2&gt;Event Listeners&lt;/h2&gt;&lt;p&gt;We&amp;#8217;ll need a few global event listeners to help us navigate through our app without refreshing the page. We mainly just hijack the default behavior and call &lt;code&gt;Backbone.history.navigate()&lt;/code&gt;. Notice how on our first listener, we&amp;#8217;re specifying the selector to only match those that don&amp;#8217;t have a data attribute of &lt;code&gt;bypass&lt;/code&gt;. This will allow us to create links such as &lt;code&gt;&amp;lt;a href=&amp;quot;/some/non-ajax/page&amp;quot; data-bypass=&amp;quot;true&amp;quot;&amp;gt;link&amp;lt;/a&amp;gt;&lt;/code&gt; that will force the page to refresh. We could also go a step further here and check whether the link is a local one, as opposed to a link to another site.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;$document.on(&amp;quot;click&amp;quot;, &amp;quot;a[href]:not([data-bypass])&amp;quot;, function(e){
  e.preventDefault();
  e.stopPropagation();

  var href = $(this).attr(&amp;quot;href&amp;quot;);
  bb.history.navigate(href, true);
});

$document.on(&amp;quot;click&amp;quot;, &amp;quot;[data-toggle='view']&amp;quot;, function(e)
{
  e.preventDefault();
  e.stopPropagation();

  var
    self = $(this),
    href = self.attr('data-target') || self.attr('href')
  ;

  bb.history.navigate(href, true);
});
&lt;/pre&gt;&lt;h3&gt;Start The App&lt;/h3&gt;&lt;p&gt;Now we just need to boot the app, passing in any config values that we need. Notice the line that checks for the &lt;code&gt;silentRouter&lt;/code&gt; global variable, this is kind of a hacky way to be able to use both back-end routing methods at the same time. This allows us to define a variable in the view called &lt;code&gt;silentRouter&lt;/code&gt; and set it to true, meaning that the router should not actually engage the backbone route, allowing our back-end to handle the initial rendering of the page, and just wait for any needed updates or AJAX.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;var BlogApp = new Blog({
  el       : $('[data-role=&amp;quot;main&amp;quot;]'),
  collection   : new PostCollection(),
  postView    : PostView,
  perPage    : 15,
  page      : 0,
  infiniteScroll : true
});

var router = new BlogRouter({
  blog: BlogApp
});

if (typeof window.silentRouter === 'undefined') window.silentRouter = true;

bb.history.start({ pushState: true, root: '/', silent: window.silentRouter });
&lt;/pre&gt;&lt;hr
/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Notice that for the Backbone portion of our app, all we had to do was write some Javascript that knew how to interact with the pre-existing portions of our application? That&amp;#8217;s what I love about this method! It may seem like we had a lot of steps to take to get to that portion of things, but really, most of that work was just a foundation build-up. Once we got that initial foundation in place, the actual application logic falls together very simply.&lt;/p&gt;&lt;p&gt;Try adding another feature to this blog, such as User listings and info. The basic steps you would take would be something like this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Use the generator tool to create a new &amp;quot;User&amp;quot; resource.&lt;/li&gt;&lt;li&gt;Make the necessary modifications to ensure that the UserController is in the V1 API group.&lt;/li&gt;&lt;li&gt;Create your Repository and setup the proper IoC bindings in &lt;code&gt;app/routes.php&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Write your Controller tests one at a time using Mockery for the repository, following each test up with the proper implementation to make sure that test passes.&lt;/li&gt;&lt;li&gt;Write your Repository tests one at a time, again, following each test up with the implementation.&lt;/li&gt;&lt;li&gt;Add in the new functionality to your Backbone App. I suggest trying two different approaches to the location of the User views. Decide for yourself which is the better implementation.&lt;ul&gt;&lt;li&gt;First place them in their own routes and Main view.&lt;/li&gt;&lt;li&gt;Then try incorporating them into the overall BlogView.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I hope this gave you some insight into creating a scalable single page app and API using Laravel 4 and Backbone.js. If you have any questions, please ask them in the comment section below!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=sp8nPXhAUws:9LeXiJXts8w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=sp8nPXhAUws:9LeXiJXts8w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=sp8nPXhAUws:9LeXiJXts8w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=sp8nPXhAUws:9LeXiJXts8w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=sp8nPXhAUws:9LeXiJXts8w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=sp8nPXhAUws:9LeXiJXts8w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=sp8nPXhAUws:9LeXiJXts8w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=sp8nPXhAUws:9LeXiJXts8w:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/sp8nPXhAUws" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/combining-laravel-4-and-backbone/feed/</wfw:commentRss> <slash:comments>58</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/combining-laravel-4-and-backbone/</feedburner:origLink></item> <item><title>New from Envato: The Easiest Way for Web Devs to Get Design Work Done</title><link>http://feedproxy.google.com/~r/nettuts/~3/-Xa3QoaAX-4/</link> <comments>http://net.tutsplus.com/articles/news/new-from-envato-the-easiest-way-for-web-devs-to-get-design-work-done/#comments</comments> <pubDate>Thu, 13 Jun 2013 20:33:03 +0000</pubDate> <dc:creator>Skellie</dc:creator> <category><![CDATA[News]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32642</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32642&amp;c=1538824329' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32642&amp;c=1538824329' border='0' alt='' /&gt;&lt;/a&gt;&lt;p
dir="ltr"&gt;As we’ve &lt;a
href="http://net.tutsplus.com/articles/editorials/this-damn-industry/"&gt;talked about before on Nettuts+&lt;/a&gt;, sometimes it feels impossible to keep up with all the skills, languages and tools you need to learn to be a great web developer.&lt;/p&gt;&lt;p
dir="ltr"&gt;In an ideal world we’d be masters of back-end, front-end and graphic design, but being truly great at any one of those three things is, on its own, a full-time challenge.&lt;/p&gt;&lt;p&gt;Many of us eventually realize that we should focus only on the skills we love to use, and let others help us with the rest.&lt;/p&gt;&lt;p
dir="ltr"&gt;For web developers, the skill we often decide we’ll never be able to master is &lt;strong&gt;design&lt;/strong&gt;.&lt;/p&gt;&lt;p
dir="ltr"&gt;And yet, we struggle on with websites and apps we know look less than great because we don’t have the time to get truly good at design, or we lack the time, energy and money to collaborate with a talented designer.&lt;/p&gt;&lt;p
dir="ltr"&gt;Envato (the people behind &lt;em&gt;Nettuts+&lt;/em&gt;) have recently launched a new service, currently in beta, that aims to solve this problem: &lt;a
href="http://microlancer.com/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Microlancer&lt;/a&gt;.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;a
href="http://microlancer.com/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch" rel="attachment wp-att-32643"&gt;&lt;img
class="alignnone size-full wp-image-32643" alt="microlancer_home" src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/microlancer_home.png" width="600" height="474" /&gt;&lt;/a&gt;&lt;/figure&gt;&lt;hr
/&gt;&lt;h2 dir="ltr"&gt;What is it?&lt;/h2&gt;&lt;p
dir="ltr"&gt;Microlancer makes it easy for web developers to access design services that are:&lt;/p&gt;&lt;ul&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;strong&gt;Affordable&lt;/strong&gt; &amp;#8211; prices are fixed and stated upfront for different types of jobs.&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;strong&gt;Discoverable&lt;/strong&gt; &amp;#8211; browse service providers and find someone with a style and approach you like.&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;strong&gt;Predictable&lt;/strong&gt; &amp;#8211; service providers state upfront how fast their turnaround time will be and how many revisions are included in the price.&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;strong&gt;Good!&lt;/strong&gt; &amp;#8211; service providers are reviewed for quality and must provide several work examples.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p
dir="ltr"&gt;Rather than committing to a big project upfront, services are broken down into smaller pieces and priced individually. For example, rebranding your web development business might involve the following services:&lt;/p&gt;&lt;ol&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/logo-design/1338-detailed-illustrated-logo-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Detailed, Illustrated Logo Design&lt;/a&gt; by DesignSyndicate ($475)&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/one-page-web-design/1367-single-page-responsive-web-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Single Page Responsive Web Design&lt;/a&gt; by kamleshyadav ($200)&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/business-card-design/588-creative-profession-business-card-designs/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Creative Professional Business Card Design&lt;/a&gt; by ShermanJackson ($60)&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/twitter-graphics/1353-twitter-background-header-design-customization/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Twitter Background, Header Design &amp;amp; Customization&lt;/a&gt; by Alex_Yves ($70)&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p
dir="ltr"&gt;These are actual services and prices currently on Microlancer, and with these, a complete rebranding with logo design, website, business cards and Twitter graphics would cost $805.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;a
href="http://www.microlancer.com/explore/business-card-design/588-creative-profession-business-card-designs/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch" rel="attachment wp-att-32656"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/creative_pro_biz_cards.png" alt="creative_pro_biz_cards" width="600" height="395" class="alignnone size-full wp-image-32656" /&gt;&lt;/a&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;p
dir="ltr"&gt;Though Microlancer is a great place to get work done for your own business, it’s also an excellent place to outsource any design work that clients need done. Prices are fixed, so it’s easy to calculate your profit margin on any given job.&lt;/p&gt;&lt;p
dir="ltr"&gt;On Microlancer, services are sold in a shop-like format, where they can be browsed and purchased individually. Though the vast majority of jobs proceed without a hitch, any issues that occasionally do arise can be resolved with Microlancer’s robust and fair dispute resolution process. Trained members of the team are on-hand to ensure that all users who play by the rules have a great Microlancer experience.&lt;/p&gt;&lt;p
dir="ltr"&gt;Here’s a quick preview of the kinds of things you can get done on Microlancer:&lt;/p&gt;&lt;ul&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/logo-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Logo Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/customize-a-psd-file/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;PSD Customization&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/image-editing/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Image Editing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/marketing-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Marketing Design&lt;/a&gt; (including &lt;a
href="http://www.microlancer.com/explore/infographics/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Infographics&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/web-banner-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Web Banner Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/print-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Print Design&lt;/a&gt; (including &lt;a
href="http://www.microlancer.com/explore/business-card-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Business Card Design&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/presentation-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Presentation Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/social-media/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Social Media Graphics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/one-page-web-design/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;Web Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li
dir="ltr"&gt;&lt;p
dir="ltr"&gt;&lt;a
href="http://www.microlancer.com/explore/web-design-ui/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;UI Element Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;&lt;p
dir="ltr"&gt;If you haven’t yet, why not take 2 minutes to &lt;a
href="http://www.microlancer.com/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;explore Microlancer&lt;/a&gt;?&lt;/p&gt;&lt;p&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr
/&gt;&lt;h2 dir="ltr"&gt;Become a Service Provider&lt;/h2&gt;&lt;p
dir="ltr"&gt;On Microlancer, users who provide services for buyers are called &amp;#8212; you guessed it &amp;#8212; service providers. Microlancer in its beta form currently offers graphic design services exclusively. If you have some design chops as well as code clout, you may be eligible to sell design services on Microlancer and unlock a new source of income.&lt;/p&gt;&lt;p
dir="ltr"&gt;Learn more about &lt;a
href="http://www.microlancer.com/sell-services/?utm_source=nettuts&amp;#038;utm_medium=blogpost&amp;#038;utm_campaign=tutslaunch"&gt;becoming a service provider on Microlancer&lt;/a&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=-Xa3QoaAX-4:8BTR1lC4bRI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=-Xa3QoaAX-4:8BTR1lC4bRI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=-Xa3QoaAX-4:8BTR1lC4bRI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=-Xa3QoaAX-4:8BTR1lC4bRI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=-Xa3QoaAX-4:8BTR1lC4bRI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=-Xa3QoaAX-4:8BTR1lC4bRI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=-Xa3QoaAX-4:8BTR1lC4bRI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=-Xa3QoaAX-4:8BTR1lC4bRI:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/-Xa3QoaAX-4" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/articles/news/new-from-envato-the-easiest-way-for-web-devs-to-get-design-work-done/feed/</wfw:commentRss> <slash:comments>4</slash:comments> <feedburner:origLink>http://net.tutsplus.com/articles/news/new-from-envato-the-easiest-way-for-web-devs-to-get-design-work-done/</feedburner:origLink></item> <item><title>Intro to Flask: Signing In and Out</title><link>http://feedproxy.google.com/~r/nettuts/~3/E4cf3iGOp7M/</link> <comments>http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-signing-in-and-out/#comments</comments> <pubDate>Wed, 12 Jun 2013 23:53:13 +0000</pubDate> <dc:creator>Lalith Polepeddi</dc:creator> <category><![CDATA[Python]]></category> <category><![CDATA[flask]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=29982</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=29982&amp;c=666825489' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=29982&amp;c=666825489' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;Many web applications require users to sign in and out in order to perform important tasks (like administration duties). In this article, we&amp;#8217;ll create an authentication system for our application.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-29982"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;In the &lt;a
href="http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-adding-a-contact-page/"&gt;previous article&lt;/a&gt;, we built a contact page using the &lt;a
href="http://packages.python.org/Flask-WTF/"&gt;Flask-WTF&lt;/a&gt; and &lt;a
href="http://packages.python.org/Flask-Mail/"&gt;Flask-Mail&lt;/a&gt; extensions. We&amp;#8217;ll use &lt;a
href="http://packages.python.org/Flask-WTF/"&gt;Flask-WTF&lt;/a&gt;, once again, this time to validate a user&amp;#8217;s username and password. We&amp;#8217;ll save these credentials into a database using yet another extension called &lt;a
href="http://packages.python.org/Flask-SQLAlchemy/"&gt;Flask-SQLAlchemy&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;You can find the source code for this tutorial on &lt;a
href="https://github.com/NETTUTS/intro-to-flask"&gt;GitHub&lt;/a&gt;. While following along with this tutorial, when you see a caption, such as &lt;code&gt;Checkpoint: 13_packaged_app&lt;/code&gt;, it means that you can switch to the GIT branch named &amp;#8220;13_packaged_app&amp;#8221; and review the code at that point in the article.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Growing the Application&lt;/h2&gt;&lt;p&gt;So far, our &lt;a
href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; app is a fairly simple application. It consists of mostly static pages; so, we&amp;#8217;ve been able to organize it as a Python module. But now, we need to reorganize our application to make it easier to maintain and grow. &lt;a
href="http://flask.pocoo.org/docs/patterns/packages/"&gt;The Flask documentation recommends&lt;/a&gt; that we reorganize the app as a Python package, so let&amp;#8217;s start there.&lt;/p&gt;&lt;p&gt;Our app is currently organized like this:&lt;/p&gt;&lt;pre&gt;flaskapp/
&amp;#9492;&amp;#9472;&amp;#9472; app/
        &amp;#9500;&amp;#9472;&amp;#9472; static/
        &amp;#9500;&amp;#9472;&amp;#9472; templates/
        &amp;#9500;&amp;#9472;&amp;#9472; forms.py
        &amp;#9500;&amp;#9472;&amp;#9472; routes.py
        &amp;#9492;&amp;#9472;&amp;#9472; README.md&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;To restructure it as a package, let&amp;#8217;s first create a new folder inside &lt;code&gt;app/&lt;/code&gt; named &lt;code&gt;intro_to_flask/&lt;/code&gt;. Then move &lt;code&gt;static/&lt;/code&gt;, &lt;code&gt;templates/&lt;/code&gt;, &lt;code&gt;forms.py&lt;/code&gt; and &lt;code&gt;routes.py&lt;/code&gt; into &lt;code&gt;intro_to_flask/&lt;/code&gt;. Also, delete any .pyc files that are hanging around.&lt;/p&gt;&lt;pre&gt;flaskapp/
&amp;#9492;&amp;#9472;&amp;#9472; app/
        &amp;#9500;&amp;#9472;&amp;#9472; intro_to_flask/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; static/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; templates/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; forms.py
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; routes.py
        &amp;#9492;&amp;#9472;&amp;#9472; README.md&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Next, create a new file named &lt;code&gt;__init__.py&lt;/code&gt; and place it inside &lt;code&gt;intro_to_flask/&lt;/code&gt;. This file is required to make Python treat the &lt;code&gt;intro_to_flask/&lt;/code&gt; folder as a package.&lt;/p&gt;&lt;pre&gt;flaskapp/
&amp;#9492;&amp;#9472;&amp;#9472; app/
        &amp;#9500;&amp;#9472;&amp;#9472; intro_to_flask/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; __init__.py
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; static/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; templates/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; forms.py
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; routes.py
        &amp;#9492;&amp;#9472;&amp;#9472; README.md&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;When our app was a Python module, the application-wide imports and configurations were specified in &lt;code&gt;routes.py&lt;/code&gt;. Now that the app is a Python package, we&amp;#8217;ll move these settings from &lt;code&gt;routes.py&lt;/code&gt; into &lt;code&gt;__init__.py&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/__init__.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from flask import Flask

app = Flask(__name__)

app.secret_key = 'development key'

app.config[&amp;quot;MAIL_SERVER&amp;quot;] = &amp;quot;smtp.gmail.com&amp;quot;
app.config[&amp;quot;MAIL_PORT&amp;quot;] = 465
app.config[&amp;quot;MAIL_USE_SSL&amp;quot;] = True
app.config[&amp;quot;MAIL_USERNAME&amp;quot;] = 'contact@example.com'
app.config[&amp;quot;MAIL_PASSWORD&amp;quot;] = 'your-password'

from routes import mail
mail.init_app(app)

import intro_to_flask.routes&lt;/pre&gt;&lt;p&gt;The top of &lt;code&gt;routes.py&lt;/code&gt; now looks like this:&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from intro_to_flask import app
from flask import render_template, request, flash
from forms import ContactForm
from flask.ext.mail import Message, Mail

mail = Mail()
.
.
.
# @app.route() mappings start here&lt;/pre&gt;&lt;p&gt;We previously had &lt;code&gt;app.run()&lt;/code&gt; inside of &lt;code&gt;routes.py&lt;/code&gt;, which allowed us to type &lt;code&gt;$ python routes.py&lt;/code&gt; to run the application. Since the app is now organized as a package, we need to employ a different strategy. &lt;a
href="http://flask.pocoo.org/docs/patterns/packages/"&gt;The Flask docs recommend&lt;/a&gt; adding a new file named &lt;code&gt;runserver.py&lt;/code&gt; and placing it inside &lt;code&gt;app/&lt;/code&gt;. Let&amp;#8217;s do that now:&lt;/p&gt;&lt;pre&gt;flaskapp/
&amp;#9492;&amp;#9472;&amp;#9472; app/
        &amp;#9500;&amp;#9472;&amp;#9472; intro_to_flask/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; __init__.py
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; static/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; templates/
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; forms.py
        &amp;#9474;      &amp;#9500;&amp;#9472;&amp;#9472; routes.py
        &amp;#9500;&amp;#9472;&amp;#9472; runserver.py        
        &amp;#9492;&amp;#9472;&amp;#9472; README.md&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Now take the &lt;code&gt;app.run()&lt;/code&gt; call from &lt;code&gt;routes.py&lt;/code&gt; and place it inside of &lt;code&gt;runserver.py&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/runserver.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from intro_to_flask import app

app.run(debug=True)&lt;/pre&gt;&lt;p&gt;Now you can type &lt;code&gt;$ python runserver.py&lt;/code&gt; and view the app in the browser. From the top, here&amp;#8217;s how you&amp;#8217;ll enter your development environment and run the app:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ cd flaskapp/
$ . bin/activate
$ cd app/
$ python runserver.py&lt;/pre&gt;&lt;p&gt;The app is now organized as a package, we&amp;#8217;re ready to move on and install a database to manage user credentials.&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 13_packaged_app&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Flask-SQLAlchemy&lt;/h2&gt;&lt;p&gt;We&amp;#8217;ll use MySQL for our database engine and the &lt;a
href="http://packages.python.org/Flask-SQLAlchemy/"&gt;Flask-SQLAlchemy&lt;/a&gt; extension to manage all of the database interaction.&lt;/p&gt;&lt;p&gt;Flask-SQLAlchemy uses Python objects instead of SQL statements to query the database. For example, instead of writing &lt;code&gt;SELECT * FROM users WHERE firstname = "lalith"&lt;/code&gt;, you would write &lt;code&gt;User.query.filter_by(username="lalith").first()&lt;/code&gt;.&lt;/p&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt; The moral of this aside is to not completely rely on, or abandon a database abstraction layer like Flask-SQLAlchemy, but to be aware of it, so that you can determine when it&amp;#8217;s useful for your needs.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;But why can&amp;#8217;t we just write raw SQL statements? What&amp;#8217;s the point of using this weird syntax? As with most things, using Flask-SQLAlchemy, or any database abstraction layer, depends on your needs and preferences. Using Flask-SQLAlchemy allows you to work with your database by writing Python code instead of SQL. This way you don&amp;#8217;t have SQL statements scattered amidst your Python code, and that&amp;#8217;s a good thing, from a code quality perspective.&lt;/p&gt;&lt;p&gt;Also, if implemented correctly, using Flask-SQLAlchemy will help make your application to be database-agnostic. If you start building your app on top of MySQL and then decide to switch to another database engine, you shouldn&amp;#8217;t have to rewrite massive chunks of sensitive database code. You could simply switch out Flask-SQLAlchemy with your new database abstraction layer without much of an issue. Being able to easily replace components is called modularity, and it&amp;#8217;s a sign of a well designed application.&lt;/p&gt;&lt;p&gt;On the other hand, it might be more intuitive and readable if you write raw SQL statements instead of learning how to translate it into Flask-SQLAlchemy&amp;#8217;s Expression Language. Fortunately, it&amp;#8217;s possible to write raw SQL statements in Flask-SQLAlchemy too, if that&amp;#8217;s what you need.&lt;/p&gt;&lt;p&gt;The moral of this aside is to not completely rely on, or abandon a database abstraction layer like Flask-SQLAlchemy, but to be aware of it, so that you can determine when it&amp;#8217;s useful for your needs. For the database queries in this article, I&amp;#8217;ll show you both the Expression Language version and the equivalent SQL statement.&lt;/p&gt;&lt;h3&gt;Installing MySQL&lt;/h3&gt;&lt;p&gt;Check to see if your system already has MySQL by running the following command in your terminal:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ mysql --version&lt;/pre&gt;&lt;p&gt;If you see a version number, you can skip to the &amp;#8220;Creating a Database&amp;#8221; section. If the command was not found, you&amp;#8217;ll need to install MySQL. With the large variety of different operating systems out there, I&amp;#8217;ll defer to Google to provide installation instructions that work for your OS. The installation usually consists of running a command or an executable. For example, the Linux command is:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ sudo apt-get install mysql-server mysql-client&lt;/pre&gt;&lt;h3&gt;Creating a Database&lt;/h3&gt;&lt;p&gt;Once MySQL is installed, create a database for your app called &amp;#8216;&lt;code&gt;development&lt;/code&gt;&amp;#8216;. You can do this from a web interface like &lt;a
href="http://www.phpmyadmin.net/home_page/index.php"&gt;phpMyAdmin&lt;/a&gt; or from the command line, as shown below:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ mysql -u username -p
Enter password:

mysql&amp;gt; CREATE DATABASE development;&lt;/pre&gt;&lt;h3&gt;Installing Flask-SQLAlchemy&lt;/h3&gt;&lt;p&gt;Inside the isolated development environment, install Flask-SQLAlchemy.&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ pip install flask-sqlalchemy&lt;/pre&gt;&lt;p&gt;When I tried to install Flask-SQLAlchemy, I received an error stating that the installation had failed. I searched the error and found that others had resolved the problem by installing &lt;code&gt;libmysqlclient15-dev&lt;/code&gt;, which installs MySQL&amp;#8217;s development files. If your Flask-SQLAlchemy installation fails, Google the error for solutions or leave a comment and we&amp;#8217;ll try to help you figure it out.&lt;/p&gt;&lt;h3&gt;Configuring Flask-SQLAlchemy&lt;/h3&gt;&lt;p&gt;Just as we did with Flask-Mail, we need to configure Flask-SQLAlchemy so that it knows where the &lt;code&gt;development&lt;/code&gt; database lives. First, create a new file named &lt;code&gt;models.py&lt;/code&gt;, along with adding in the following code&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/models.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from flask.ext.sqlalchemy import SQLAlchemy

db = SQLAlchemy()&lt;/pre&gt;&lt;p&gt;Here we import the &lt;code&gt;SQLAlchemy&lt;/code&gt; class from Flask-SQLAlchemy (line one) and create a variable named &lt;code&gt;db&lt;/code&gt;, containing a usable instance of the &lt;code&gt;SQLAlchemy&lt;/code&gt; class (line three).&lt;/p&gt;&lt;p&gt;Next, open &lt;code&gt;__init__.py&lt;/code&gt; and add the following lines after &lt;code&gt;mail.init_app(app)&lt;/code&gt; and before &lt;code&gt;import intro_to_flask.routes&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/__init__.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://your-username:your-password@localhost/development'

from models import db
db.init_app(app)&lt;/pre&gt;&lt;p&gt;Let&amp;#8217;s go over this:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Line one tells the Flask app to use the &amp;#8216;&lt;code&gt;development&lt;/code&gt;&amp;#8216; database. We specify this through a data URI which follows the pattern of: &lt;code&gt;mysql://username:password@server/database&lt;/code&gt;. The server is &amp;#8216;localhost&amp;#8217; because we&amp;#8217;re developing locally. Make sure to fill in your MySQL &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;code&gt;db&lt;/code&gt;, the usable instance of the &lt;code&gt;SQLAlchemy&lt;/code&gt; class we created in &lt;code&gt;models.py&lt;/code&gt;, still doesn&amp;#8217;t know what database to use. So we import it from &lt;code&gt;models.py&lt;/code&gt; (line three) and bind it to our app (line four), so that it also knows to use the &amp;#8216;&lt;code&gt;development&lt;/code&gt;&amp;#8216; database. We can now query the &amp;#8216;&lt;code&gt;development&lt;/code&gt;&amp;#8216; database through our &lt;code&gt;db&lt;/code&gt; object.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Now that our configuration is complete, let&amp;#8217;s ensure that everything works. Open &lt;code&gt;routes.py&lt;/code&gt; and create a temporary URL mapping so that we can perform a test query.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro-to-flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from intro_to_flask import app
from flask import Flask, render_template, request, flash, session, redirect, url_for
from forms import ContactForm, SignupForm, SigninForm
from flask.ext.mail import Message, Mail
from models import db
.
.
.
@app.route('/testdb')
def testdb():
  if db.session.query(&amp;quot;1&amp;quot;).from_statement(&amp;quot;SELECT 1&amp;quot;).all():
    return 'It works.'
  else:
    return 'Something is broken.'&lt;/pre&gt;&lt;p&gt;First we import the database object (&lt;code&gt;db&lt;/code&gt;) from &lt;code&gt;models.py&lt;/code&gt; (line five). We then create a temporary URL mapping (lines 9-14) wherein we issue a test query to ensure that the Flask app is connected to the &amp;#8216;&lt;code&gt;development&lt;/code&gt;&amp;#8216; database. Now when we visit the URL &lt;code&gt;/testdb&lt;/code&gt;, a test query will be issued (line 11); this is equivalent to the SQL statement &lt;code&gt;SELECT 1;&lt;/code&gt;. If all goes well, we&amp;#8217;ll see &amp;#8220;&lt;strong&gt;It works&lt;/strong&gt;&amp;#8221; in the browser. Otherwise, we&amp;#8217;ll see an error message stating what went wrong.&lt;/p&gt;&lt;p&gt;I received an error when I visited the &lt;code&gt;/testdb&lt;/code&gt; URL: &lt;code&gt;ImportError: No module named MySQLdb&lt;/code&gt;. This meant that I didn&amp;#8217;t have the mysql-python library installed, so I tried to install it by typing the following:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ pip install mysql-python&lt;/pre&gt;&lt;p&gt;That installation failed, too. The new error message suggested that I first run &lt;code&gt;easy_install -U distribute&lt;/code&gt; and then try the mysql-python installation again. So I did, just like below:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ easy_install -U distribute
$ pip install mysql-python&lt;/pre&gt;&lt;p&gt;This time the mysql-python installation succeeded, and then I received the &amp;#8220;&lt;strong&gt;It works&lt;/strong&gt;&amp;#8221; success message in the browser. Now the reason I&amp;#8217;m recounting the errors I&amp;#8217;ve received and what I did to solve them is because installing and connecting to databases can be a tricky process. If you get an error message, please don&amp;#8217;t get discouraged. Google the error message or leave a comment, and we&amp;#8217;ll figure it out.&lt;/p&gt;&lt;p&gt;Once the test query works, delete the temporary URL mapping from &lt;code&gt;routes.py&lt;/code&gt;. Make sure to retain the &amp;#8220;&lt;code&gt;from models import db&lt;/code&gt;&amp;#8220;&amp;#8221; part, because we&amp;#8217;ll need it next.&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 14_db_config&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Create a User Model&lt;/h2&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;It&amp;#8217;s not a good idea to store passwords in plain text, for security reasons.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Inside the &amp;#8216;&lt;code&gt;development&lt;/code&gt;&amp;#8216; database, we need to create a users table where we can store each user&amp;#8217;s information. The information we want to collect and store are the user&amp;#8217;s first name, last name, email, and password.&lt;/p&gt;&lt;p&gt;It&amp;#8217;s not a good idea to store passwords in plain text, for security reasons. If an attacker gains access to your database, they would be able to see each user&amp;#8217;s login credentials. One way to defend against such an attack is to encrypt passwords with a hash function and a &lt;code&gt;salt&lt;/code&gt; (some random data), and store that encrypted value in the database instead of the plain text password. When a user signs in again, we&amp;#8217;ll collect the password that was submitted, hash it, and check if it matches the hash in the database. Werkzeug, the utility library on which Flask is built, provides the functions &lt;code&gt;generate_password_hash&lt;/code&gt; and &lt;code&gt;check_password_hash&lt;/code&gt; for these two tasks, respectively.&lt;/p&gt;&lt;p&gt;With this in mind, here are the columns we&amp;#8217;ll need for the users table:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Column&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Constraints&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;uid&lt;/td&gt;&lt;td&gt;int&lt;/td&gt;&lt;td&gt;Primary Key, Auto Increment&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;firstname&lt;/td&gt;&lt;td&gt;varchar(100)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;lastname&lt;/td&gt;&lt;td&gt;varchar(100)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;email&lt;/td&gt;&lt;td&gt;varchar(120)&lt;/td&gt;&lt;td&gt;Unique&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;password&lt;/td&gt;&lt;td&gt;varchar(54)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Just like before, you can create this table from a web interface such as phpMyAdmin or from the command line, as shown below:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;mysql&amp;gt; CREATE TABLE users (
uid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
firstname VARCHAR(100) NOT NULL,
lastname VARCHAR(100) NOT NULL,
email VARCHAR(120) NOT NULL UNIQUE,
pwdhash VARCHAR(100) NOT NULL
);&lt;/pre&gt;&lt;p&gt;Next, in &lt;code&gt;models.py&lt;/code&gt;, let&amp;#8217;s create a class to model a user with attributes for a user&amp;#8217;s first name, last name, email, and password.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/models.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from flask.ext.sqlalchemy import SQLAlchemy
from werkzeug import generate_password_hash, check_password_hash

db = SQLAlchemy()

class User(db.Model):
  __tablename__ = 'users'
  uid = db.Column(db.Integer, primary_key = True)
  firstname = db.Column(db.String(100))
  lastname = db.Column(db.String(100))
  email = db.Column(db.String(120), unique=True)
  pwdhash = db.Column(db.String(54))
  
  def __init__(self, firstname, lastname, email, password):
    self.firstname = firstname.title()
    self.lastname = lastname.title()
    self.email = email.lower()
    self.set_password(password)
    
  def set_password(self, password):
    self.pwdhash = generate_password_hash(password)
  
  def check_password(self, password):
    return check_password_hash(self.pwdhash, password)&lt;/pre&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;We use the set_password() function to set a salted hash of the password, instead of using the plain text password itself.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Lines one and four already existed in &lt;code&gt;models.py&lt;/code&gt;, so we&amp;#8217;ll start on line two by importing the &lt;code&gt;generate_password_hash&lt;/code&gt; and &lt;code&gt;check_password_hash&lt;/code&gt; security functions from Werkzeug. Next, we create a new class named &lt;code&gt;User&lt;/code&gt;, inheriting from the database object &lt;code&gt;db&lt;/code&gt;&amp;#8216;s &lt;code&gt;Model&lt;/code&gt; class (line six.)&lt;/p&gt;&lt;p&gt;Inside of our &lt;code&gt;User&lt;/code&gt; class, we create attributes for the table&amp;#8217;s name, primary key, and the user&amp;#8217;s first name, last name, email, and password (lines 10-14). We then write a constructor which sets the class attributes (lines 17-20). We save names in title case and email addresses in lowercase to ensure a match regardless of how a user types in his credentials on subsequent sign ins.&lt;/p&gt;&lt;p&gt;We use the &lt;code&gt;set_password&lt;/code&gt; function (lines 22-23) to set a salted hash of the password, instead of using the plain text password itself. Lastly, we have a function named &lt;code&gt;check_password&lt;/code&gt; that uses &lt;code&gt;check_password_hash&lt;/code&gt;, to check a user&amp;#8217;s credentials on any subsequent sign ins (lines 25-26).&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 15_user_model&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;p&gt;Sweet! We&amp;#8217;ve created a users table and a user model, thereby laying down the foundation of our authentication system. Now let&amp;#8217;s build the first user-facing component of the authentication system: the signup page.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Building a Signup Page&lt;/h2&gt;&lt;h3&gt;Planning&lt;/h3&gt;&lt;p&gt;Take a look at &lt;code&gt;Fig. 1&lt;/code&gt; below, to see how everything will fit together.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/authors/lalith-polepeddi/intro-to-flask-p3-fig1.png" alt="The Sign up process." /&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;Fig. 1&lt;/code&gt;&lt;/p&gt; &lt;/figure&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;Implement SSL site-wide so that passwords and session tokens cannot be intercepted.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Let&amp;#8217;s go over the figure from above:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;A user visits the URL &lt;code&gt;/signup&lt;/code&gt; to create a new account. The page is retrieved through an HTTP GET request and loads in the browser.&lt;/li&gt;&lt;li&gt;The user fills in the form fields with his first name, last name, email, and password.&lt;/li&gt;&lt;li&gt;The user clicks the &amp;#8220;Create account&amp;#8221; button, and the form submits to the server with an HTTP POST request.&lt;/li&gt;&lt;li&gt;On the server, a function validates the form data.&lt;/li&gt;&lt;li&gt;If one or more fields do not pass validation, the signup page reloads with a helpful error message, prompting the the user to try again.&lt;/li&gt;&lt;li&gt;If all fields are valid, a new &lt;code&gt;User&lt;/code&gt; object will be created and saved into the database. The user will then be signed in and redirected to a profile page.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This sequence of steps should look familiar, as it&amp;#8217;s identical to the sequence of steps we took to create a contact form. Here, instead of sending an email at the end, we save a user&amp;#8217;s credentials to the database. The &lt;a
href="http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-adding-a-contact-page/"&gt;previous article&lt;/a&gt; already explained creating a form in detail, I&amp;#8217;ll move more quickly in this section so that we can get to the more exciting parts, faster.&lt;/p&gt;&lt;h3&gt;Creating a Signup Form&lt;/h3&gt;&lt;p&gt;We installed Flask-WTF in the &lt;a
href="http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-adding-a-contact-page/"&gt;previous article&lt;/a&gt;, so let&amp;#8217;s proceed with creating a new form inside &lt;code&gt;forms.py&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/forms.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators, ValidationError, PasswordField
from models import db, User
.
.
.
class SignupForm(Form):
  firstname = TextField(&amp;quot;First name&amp;quot;,  [validators.Required(&amp;quot;Please enter your first name.&amp;quot;)])
  lastname = TextField(&amp;quot;Last name&amp;quot;,  [validators.Required(&amp;quot;Please enter your last name.&amp;quot;)])
  email = TextField(&amp;quot;Email&amp;quot;,  [validators.Required(&amp;quot;Please enter your email address.&amp;quot;), validators.Email(&amp;quot;Please enter your email address.&amp;quot;)])
  password = PasswordField('Password', [validators.Required(&amp;quot;Please enter a password.&amp;quot;)])
  submit = SubmitField(&amp;quot;Create account&amp;quot;)

  def __init__(self, *args, **kwargs):
    Form.__init__(self, *args, **kwargs)

  def validate(self):
    if not Form.validate(self):
      return False
    
    user = User.query.filter_by(email = self.email.data.lower()).first()
    if user:
      self.email.errors.append(&amp;quot;That email is already taken&amp;quot;)
      return False
    else:
      return True&lt;/pre&gt;&lt;p&gt;We start by importing one more Flask-WTF class named &lt;code&gt;PasswordField&lt;/code&gt; (line one), which is like &lt;code&gt;TextField&lt;/code&gt; except that it generates a password textbox. We&amp;#8217;ll need the &lt;code&gt;db&lt;/code&gt; database object and the &lt;code&gt;User&lt;/code&gt; model to handle some custom validation logic inside the &lt;code&gt;SignupForm&lt;/code&gt; class; so we import them too (line two).&lt;/p&gt;&lt;p&gt;Then we create a new class named &lt;code&gt;SignupForm&lt;/code&gt; containing a field for each piece of user information we wish to collect (lines 7-11). There&amp;#8217;s a presence validator on each field to ensure it&amp;#8217;s filled in, and a format validator which requires that email addresses match the pattern: &lt;code&gt;user@example.com&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Next, we write a simple constructor for the class that just calls the base class&amp;#8217; constructor (lines 13-14).&lt;/p&gt;&lt;p&gt;So we&amp;#8217;ve added some presence and format validators to our form fields, but we need an additional validator that ensures an account does not already exist with the user&amp;#8217;s email address. To do this we hook into Flask-WTF&amp;#8217;s validation process (lines 16-25).&lt;/p&gt;&lt;p&gt;Now inside of the &lt;code&gt;validate()&lt;/code&gt; function, we first ensure the presence and format validators run by calling the base class&amp;#8217; &lt;code&gt;validate()&lt;/code&gt; method; if the form is not filled in properly, &lt;code&gt;validate()&lt;/code&gt; returns &lt;code&gt;False&lt;/code&gt; (lines 16-17).&lt;/p&gt;&lt;p&gt;Next we define the custom validator. We start by querying the database with the email that the user submitted (line 18). If you remember from our &lt;code&gt;models.py&lt;/code&gt; file, the email address is converted to lowercase to ensure a match regardless of how it was typed in. This Flask-SQLAlchemy expression corresponds to the following SQL statement:&lt;/p&gt;&lt;pre class="brush: sql; title: ; notranslate"&gt;SELECT * FROM users 
  WHERE email = self.email.data.lower() 
  LIMIT 1&lt;/pre&gt;&lt;p&gt;If a user record already exists with the submitted email, validation fails giving the following error message: &amp;#8220;&lt;strong&gt;That email is already taken&lt;/strong&gt;&amp;#8221; (lines 21-22).&lt;/li&gt;&lt;h3&gt;Using the Signup Form&lt;/h3&gt;&lt;p&gt;Let&amp;#8217;s now create a new URL mapping and a new web template for the signup form. Open &lt;code&gt;routes.py&lt;/code&gt; and import the newly created signup form so that we can use it.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from intro_to_flask import app
from flask import render_template, request, flash
from forms import ContactForm, SignupForm&lt;/pre&gt;&lt;p&gt;Next, create a new URL mapping.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;@app.route('/signup', methods=['GET', 'POST'])
def signup():
  form = SignupForm()
  
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signup.html', form=form)
    else:   
      return &amp;quot;[1] Create a new user [2] sign in the user [3] redirect to the user's profile&amp;quot;
  
  elif request.method == 'GET':
    return render_template('signup.html', form=form)&lt;/pre&gt;&lt;p&gt;Inside the &lt;code&gt;signup()&lt;/code&gt; function, we create a variable named &lt;code&gt;form&lt;/code&gt; that contains a usable instance of the &lt;code&gt;SignupForm&lt;/code&gt; class. If a GET request has been issued, we&amp;#8217;ll return the &lt;code&gt;signup.html&lt;/code&gt; web template containing the signup form for the user to fill out.&lt;/p&gt;&lt;p&gt;Otherwise, we&amp;#8217;ll see just a temporary placeholder string. For now, the temp string lists the three actions that should take place when the form has been successfully submitted. We&amp;#8217;ll come back and replace this string with real code in &amp;#8220;The First Signup&amp;#8221; section below.&lt;/p&gt;&lt;p&gt;Now that we&amp;#8217;ve created a URL mapping, the next step is to create the web template &lt;code&gt;signup.html&lt;/code&gt; and place it inside the &lt;code&gt;templates/&lt;/code&gt; folder.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/templates/signup.html&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;{% extends &amp;quot;layout.html&amp;quot; %}

{% block content %}
  &amp;lt;h2&amp;gt;Sign up&amp;lt;/h2&amp;gt;

  {% for message in form.firstname.errors %}
    &amp;lt;div class=&amp;quot;flash&amp;quot;&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
  {% endfor %}
  
  {% for message in form.lastname.errors %}
    &amp;lt;div class=&amp;quot;flash&amp;quot;&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
  {% endfor %}
  
  {% for message in form.email.errors %}
    &amp;lt;div class=&amp;quot;flash&amp;quot;&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
  {% endfor %}
  
  {% for message in form.password.errors %}
    &amp;lt;div class=&amp;quot;flash&amp;quot;&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
  {% endfor %}
  
  &amp;lt;form action=&amp;quot;{{ url_for('signup') }}&amp;quot; method=post&amp;gt;
    {{ form.hidden_tag() }}
    
    {{ form.firstname.label }}
    {{ form.firstname }}
    
    {{ form.lastname.label }}
    {{ form.lastname }}
    
    {{ form.email.label }}
    {{ form.email }}
    
    {{ form.password.label }}
    {{ form.password }}
    
    {{ form.submit }}
  &amp;lt;/form&amp;gt;
    
{% endblock %}&lt;/pre&gt;&lt;p&gt;This template looks just like &lt;code&gt;contact.html&lt;/code&gt;. We first loop through and display any error messages if necessary. We then let Jinja2 generate most of the HTML form for us. Remember how in the &lt;code&gt;Signup&lt;/code&gt; form class we appended the error message &amp;#8220;&lt;strong&gt;That email is already taken&lt;/strong&gt;&amp;#8221; to &lt;code&gt;self.email.errors&lt;/code&gt;? That&amp;#8217;s the same object that Jinja2 loops through in this template.&lt;/p&gt;&lt;p&gt;The one difference from the &lt;code&gt;contact.html&lt;/code&gt; template is the omission of the &lt;code&gt;if...else&lt;/code&gt; logic.&lt;/p&gt;&lt;p&gt;In this template, we want to register and sign in the user on a successful form submission. This takes place on the back-end, so the &lt;code&gt;if...else&lt;/code&gt; statement is not needed here.&lt;/p&gt;&lt;p&gt;Finally, add in these CSS rules to your &lt;code&gt;main.css&lt;/code&gt; file so that the signup form looks nice and pretty.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/static/css/main.css&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: css; title: ; notranslate"&gt;/* Signup form */
form input#firstname,
form input#lastname,
form input#password {
  width: 400px;
  background-color: #fafafa;
  -webkit-border-radius: 3px;
     -moz-border-radius: 3px;
          border-radius: 3px;
  border: 1px solid #cccccc;
  padding: 5px;
  font-size: 1.1em;
}

form input#password {
  margin-bottom: 10px;
}&lt;/pre&gt;&lt;p&gt;Let&amp;#8217;s check out the newly created signup page by typing:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ cd app/
$ python runserver.py&lt;/pre&gt;&lt;p&gt;And browse to &lt;a
href="http://localhost:5000/signup"&gt;http://localhost:5000/signup&lt;/a&gt; in your favorite web browser.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/authors/lalith-polepeddi/intro-to-flask-p3-signup.png" alt="The sign up page." /&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;p&gt;Excellent! We just created a signup form from scratch, handled complex validation, and created a good looking signup page with helpful error messages.&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 16_signup_form&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;p&gt;If any of these steps were unclear, please take a moment to review the &lt;a
href="http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-adding-a-contact-page/"&gt;previous article&lt;/a&gt;. It covers each step in greater detail, and I followed the same steps from that article, to create this signup form.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;The First Signup&lt;/h2&gt;&lt;p&gt;Let&amp;#8217;s start by replacing the temporary placeholder string in &lt;code&gt;routes.py&lt;/code&gt;&amp;#8216;s &lt;code&gt;signup()&lt;/code&gt; function with some real code. Upon a successful form submission, we need to create a new &lt;code&gt;User&lt;/code&gt; object, save it to the database, sign the user in, and redirect to the user&amp;#8217;s profile page. Let&amp;#8217;s take this step by step, starting with creating a new &lt;code&gt;User&lt;/code&gt; object and saving it to the database.&lt;/p&gt;&lt;h3&gt;Saving a New User Object&lt;/h3&gt;&lt;p&gt;Add in lines five and 17-19 to&lt;p&gt;&lt;code&gt;routes.py.&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from intro_to_flask import app
from flask import render_template, request, flash, session, url_for, redirect
from forms import ContactForm, SignupForm
from flask.ext.mail import Message, Mail
from models import db, User
.
.
.
@app.route('/signup', methods=['GET', 'POST'])
def signup():
  form = SignupForm()
  
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signup.html', form=form)
    else:
      newuser = User(form.firstname.data, form.lastname.data, form.email.data, form.password.data)
      db.session.add(newuser)
      db.session.commit()
      
      return &amp;quot;[1] Create a new user [2] sign in the user [3] redirect to the user's profile&amp;quot;
  
  elif request.method == 'GET':
    return render_template('signup.html', form=form)&lt;/pre&gt;&lt;p&gt;First, we import the &lt;code&gt;User&lt;/code&gt; class from &lt;/code&gt;models.py&lt;/code&gt; so that we can use it in the &lt;code&gt;signup()&lt;/code&gt; function (line five). Then we create a new &lt;code&gt;User&lt;/code&gt; object called &lt;code&gt;newuser&lt;/code&gt; and populate it with the signup form's field data (line 17).&lt;/p&gt;&lt;p&gt;Next, we add &lt;code&gt;newuser&lt;/code&gt; to the database object's session (line 18), which is Flask-SQLAlchemy's version of a regular database transaction. The &lt;code&gt;add()&lt;/code&gt; function generates an &lt;code&gt;INSERT&lt;/code&gt; statement using the &lt;code&gt;User&lt;/code&gt; object's attributes. The equivalent SQL for this Flask-SQLAlchemy expression is:&lt;/p&gt;&lt;pre class="brush: sql; title: ; notranslate"&gt;  INSERT INTO users (firstname, lastname, email, pwdhash)
  VALUES (form.firstname.data, form.lastname.data, form.email.data, form.password.data)  &lt;/pre&gt;&lt;p&gt;Lastly, we update the database with the new user record by committing the transaction (line 19).&lt;/p&gt;&lt;h3&gt;Signing in the User&lt;/h3&gt;&lt;p&gt;Next, we need to sign in the user. The Flask app needs to know that subsequent page requests are coming from the browser of the user who has successfully signed up. We can accomplish this by setting a cookie in the user's browser containing some sort of ID and associating that key with the user's credentials in the Flask app.&lt;/p&gt;&lt;p&gt;This way, the ID in the browser's cookie will be passed to the app on each subsequent page request, and the app will look up the ID to determine whether it maps to valid user credentials.&lt;/p&gt;&lt;p&gt;If it does, the app allows access to the parts of the website that you need to be signed in for. This combination of having a key stored on the client and a value stored on the server is called a session.&lt;/p&gt;&lt;p&gt;Flask has a &lt;code&gt;session&lt;/code&gt; object that accomplishes this functionality. It stores the session key in a secure cookie on the client and the session value in the app. Let's use it in our &lt;code&gt;signup()&lt;/code&gt; function.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;from flask import render_template, request, flash, session
.
.
.
@app.route('/signup', methods=['GET', 'POST'])
def signup():
  form = SignupForm()
  
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signup.html', form=form)
    else:
      newuser = User(form.firstname.data, form.lastname.data, form.email.data, form.password.data)
      db.session.add(newuser)
      db.session.commit()
      
      session['email'] = newuser.email
      
      return &amp;quot;[1] Create a new user [2] sign in the user [3] redirect to the user's profile&amp;quot;
  
  elif request.method == 'GET':
    return render_template('signup.html', form=form)&lt;/pre&gt;&lt;p&gt;We start by importing Flask's &lt;code&gt;session&lt;/code&gt; object on line one. Next, we associate the key '&lt;code&gt;email&lt;/code&gt;' with the value of the newly registered user's email (line 17). The &lt;code&gt;session&lt;/code&gt; object will take care of hashing '&lt;code&gt;email&lt;/code&gt;' into an excrypted ID and storing it in a cookie on the user's browser. At this point, the user is signed in to our app.&lt;/p&gt;&lt;h3&gt;Redirecting to a Profile page&lt;/h3&gt;&lt;p&gt;The last step is to redirect the user to a Profile page after signing in. We'll use the &lt;code&gt;url_for&lt;/code&gt; function (which we've seen in &lt;code&gt;layout.html&lt;/code&gt; and &lt;code&gt;contact.html&lt;/code&gt;) in conjunction with Flask's &lt;code&gt;redirect()&lt;/code&gt; function.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
from intro_to_flask import app
from flask import render_template, request, flash, session, url_for, redirect
.
.
.
@app.route('/signup', methods=['GET', 'POST'])
def signup():
  form = SignupForm()
  
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signup.html', form=form)
    else:
      newuser = User(form.firstname.data, form.lastname.data, form.email.data, form.password.data)
      db.session.add(newuser)
      db.session.commit()
      
      session['email'] = newuser.email
      return redirect(url_for('profile'))
  
  elif request.method == 'GET':
    return render_template('signup.html', form=form)
&lt;/pre&gt;&lt;p&gt;on line two, we import Flask's &lt;code&gt;url_for()&lt;/code&gt; and &lt;code&gt;redirect()&lt;/code&gt; functions. Then on line 19, we replace our temporary placeholder string with a redirect to the URL &lt;code&gt;/profile&lt;/code&gt;. We don't have a URL mapping for &lt;code&gt;/profile&lt;/code&gt; yet, so let's create that next.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
@app.route('/profile')
def profile():

  if 'email' not in session:
    return redirect(url_for('signin'))

  user = User.query.filter_by(email = session['email']).first()

  if user is None:
    return redirect(url_for('signin'))
  else:
    return render_template('profile.html')
&lt;/pre&gt;&lt;p&gt;Here we can finally see sessions in action. We start on line four by fetching the browser's cookie and checking if it contains a key named '&lt;code&gt;email&lt;/code&gt;'. If it doesn't exist, that means the user is not authenticated, so we redirect the user to a signin page (we'll create this in the next section).&lt;/p&gt;&lt;p&gt;If the '&lt;code&gt;email&lt;/code&gt;' key does exist, we look up the server-side user email value associated with the key using &lt;code&gt;session['email']&lt;/code&gt;, and then query the database for a registered user with this same email address (line seven). The equivalent SQL for this Flask-SQLAlchemy expression is:&lt;/p&gt;&lt;pre class="brush: sql; title: ; notranslate"&gt;SELECT * FROM users WHERE email = session['email'];&lt;/pre&gt;&lt;p&gt;If no registered user exists, we'll redirect to the signup page. Otherwise, we render the &lt;code&gt;profile.html&lt;/code&gt; template. Let's create &lt;code&gt;profile.html&lt;/code&gt; now.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/templates/profile.html&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;{% extends &amp;quot;layout.html&amp;quot; %}
{% block content %}
  &amp;lt;div class=&amp;quot;jumbo&amp;quot;&amp;gt;
    &amp;lt;h2&amp;gt;Profile&amp;lt;h2&amp;gt;
    &amp;lt;h3&amp;gt;This is {{ session['email'] }}'s profile page&amp;lt;h3&amp;gt;
  &amp;lt;/div&amp;gt;
{% endblock %}&lt;/pre&gt;&lt;p&gt;I've kept this profile template simple. If we focus in on line five &amp;mdash; you'll see that we can use Flask's &lt;code&gt;session&lt;/code&gt; object inside Jinja2 templates. Here, I've used it to create a user-specific string, but you could use this ability to pull other types of user-specific information instead.&lt;/p&gt;&lt;p&gt;We're finally ready to see the result of all our hard work. Type the following into your terminal:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;$ python runserver.py&lt;/pre&gt;&lt;p&gt;Go to &lt;a
href="http://localhost:5000/signup"&gt;http://localhost:5000/&lt;/a&gt; in your favorite web browser, and complete the sign up process. You should be greeted with a profile page that looks like the following screenshot:&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/authors/lalith-polepeddi/intro-to-flask-p3-profile.png" alt="A successful sign up!" /&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;p&gt;Signing up users is a huge milestone for our app. We can adapt the code in our &lt;code&gt;/signup()&lt;/code&gt; function and round out our authentication system by allowing users to sign in and out of the app.&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 17_profile_page&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Building a Signin Page&lt;/h2&gt;&lt;p&gt;Creating a signin page is similar to creating a signup page &amp;mdash; we'll need to create a signin form, a URL mapping, and a web template. Let's start by creating the &lt;code&gt;SigninForm&lt;/code&gt; class in &lt;code&gt;forms.py&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/forms.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;class SigninForm(Form):
  email = TextField(&amp;quot;Email&amp;quot;,  [validators.Required(&amp;quot;Please enter your email address.&amp;quot;), validators.Email(&amp;quot;Please enter your email address.&amp;quot;)])
  password = PasswordField('Password', [validators.Required(&amp;quot;Please enter a password.&amp;quot;)])
  submit = SubmitField(&amp;quot;Sign In&amp;quot;)
  
  def __init__(self, *args, **kwargs):
    Form.__init__(self, *args, **kwargs)

  def validate(self):
    if not Form.validate(self):
      return False
    
    user = User.query.filter_by(email = self.email.data.lower()).first()
    if user and user.check_password(self.password.data):
      return True
    else:
      self.email.errors.append(&amp;quot;Invalid e-mail or password&amp;quot;)
      return False&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;SigninForm&lt;/code&gt; class is similar to the &lt;code&gt;SignupForm&lt;/code&gt; class. To sign a user in, we need to capture their email and password, so we create those two fields with presence and format validators (lines 2-3). Then we define our custom validator inside the &lt;code&gt;validate()&lt;/code&gt; function (lines 10-15). This time the validator needs to make sure the user exists in the database and has the correct password. If a record does exist with the supplied information, we check to see if the password matches (line 14). If it does, the validation check passes (line 15), otherwise they get an error message.&lt;/p&gt;&lt;p&gt;Next, let's create a URL mapping in &lt;code&gt;routes.py&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
...
from forms import ContactForm, SignupForm, SigninForm
.
.
.
@app.route('/signin', methods=['GET', 'POST'])
def signin():
  form = SigninForm()
  
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signin.html', form=form)
    else:
      session['email'] = form.email.data
      return redirect(url_for('profile'))
                
  elif request.method == 'GET':
    return render_template('signin.html', form=form) 
&lt;/pre&gt;&lt;p&gt;Once again, the &lt;code&gt;signin()&lt;/code&gt; function is similar to the &lt;code&gt;signup()&lt;/code&gt; function. We import &lt;code&gt;SigninForm&lt;/code&gt; (line two), so that we can use it in the &lt;code&gt;signin()&lt;/code&gt; function. Then in &lt;code&gt;signin()&lt;/code&gt;, we return the &lt;code&gt;signin.html&lt;/code&gt; template for GET requests (lines 17-18).&lt;/p&gt;&lt;p&gt;If the form has been POSTed and any validation check fails, the signin form reloads with a helpful error message (lines 11-12). Otherwise, we sign in the user by creating a new session and redirecting to their profile page (lines 14-15).&lt;/p&gt;&lt;p&gt;Lastly, let's create the web template &lt;code&gt;signin.html&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/templates/signin.html&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;{% extends &amp;quot;layout.html&amp;quot; %}

{% block content %}
  &amp;lt;h2&amp;gt;Sign In&amp;lt;/h2&amp;gt;

  {% for message in form.email.errors %}
    &amp;lt;div class=&amp;quot;flash&amp;quot;&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
  {% endfor %}
  
  {% for message in form.password.errors %}
    &amp;lt;div class=&amp;quot;flash&amp;quot;&amp;gt;{{ message }}&amp;lt;/div&amp;gt;
  {% endfor %}
  
  &amp;lt;form action=&amp;quot;{{ url_for('signin') }}&amp;quot; method=post&amp;gt;
    {{ form.hidden_tag() }}
    
    {{ form.email.label }}
    {{ form.email }}
    
    {{ form.password.label }}
    {{ form.password }}
    
    {{ form.submit }}
  &amp;lt;/form&amp;gt;
    
{% endblock %}&lt;/pre&gt;&lt;p&gt;Similar to &lt;code&gt;signup.html&lt;/code&gt; template, we first loop through and display any error messages, then we let Jinja2 generate the form for us.&lt;/p&gt;&lt;p&gt;And that does it for the signin page. Visit &lt;a
href="http://localhost:5000/signin"&gt;http://localhost:5000/signin&lt;/a&gt; to check it out. Go ahead and sign in, you should get redirected to your profile page.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/authors/lalith-polepeddi/intro-to-flask-p3-signin.png" alt="A successful sign in." /&gt;&lt;br
/&gt; &lt;/figure&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 18_signin_form&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Signing Out&lt;/h2&gt;&lt;p&gt;In "The First Signup" section above, we saw that "signing in" meant setting a cookie in the user's browser containing an ID and associating that ID with the user's data in the Flask app. Therefore, "signing out" means clearing the cookie in the browser and dissociating the user data.&lt;/p&gt;&lt;p&gt;This can be accomplished in one line: &lt;code&gt;session.pop('email', None)&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;We don't need a form or even a web template to sign out. All we need is a URL mapping in &lt;code&gt;routes.py&lt;/code&gt;, which terminates the session and redirects to the Home page. The mapping, therefore, is short and sweet:&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;@app.route('/signout')
def signout():

  if 'email' not in session:
    return redirect(url_for('signin'))
    
  session.pop('email', None)
  return redirect(url_for('home'))&lt;/pre&gt;&lt;p&gt;The user is not authenticated if the browser's cookie does not contain a key named '&lt;code&gt;email&lt;/code&gt;', in that case, we just redirect to the signin page (lines 4-5). Otherwise, we terminate the session (line seven) and redirect back to the home page (line eight).&lt;/p&gt;&lt;p&gt;You can test the sign out functionality by visiting &lt;a
href="http://localhost:5000/signout"&gt;http://localhost:5000/signout&lt;/a&gt;. If you're signed in, the app will sign you out and redirect to &lt;a
href="http://localhost:5000/"&gt;http://localhost:5000/&lt;/a&gt;. Once you've signed out, try visiting the profile page &lt;a
href="http://localhost:5000/profile"&gt;http://localhost:5000/profile&lt;/a&gt;. You shouldn't be allowed to see the profile page if you're not signed in, and the app should redirect you back to the Signin page.&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 19_signout&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Tidying Up&lt;/h2&gt;&lt;p&gt;Now we need to update the site header with navigation links for "Sign Up", "Sign In", "Profile", and "Sign Out". The links should change based on whether the user is signed in or not. If the user is signed out, links for "Sign Up" and "Sign In" should be visible. When the user is signed in, we want links for "Profile" and "Sign Out" to appear, while hiding the "Sign Up" and "Sign In" links.&lt;/p&gt;&lt;p&gt;So how can we do this? Think back to the &lt;code&gt;profile.html&lt;/code&gt; template where we used Flask's &lt;code&gt;session&lt;/code&gt; object. We can use the &lt;code&gt;session&lt;/code&gt; object to show navigation links based on the user's authentication status. Let's open &lt;code&gt;layout.html&lt;/code&gt; and make the following changes:&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/templates/layout.html&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Flask App&amp;lt;/title&amp;gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;{{ url_for('static', filename='css/main.css') }}&amp;quot;&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;

  &amp;lt;header&amp;gt;
    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
      &amp;lt;h1 class=&amp;quot;logo&amp;quot;&amp;gt;Flask App&amp;lt;/h1&amp;gt;
      &amp;lt;nav&amp;gt;
        &amp;lt;ul class=&amp;quot;menu&amp;quot;&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('home') }}&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('about') }}&amp;quot;&amp;gt;About&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('contact') }}&amp;quot;&amp;gt;Contact&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          {% if 'email' in session %}
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('profile') }}&amp;quot;&amp;gt;Profile&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('signout') }}&amp;quot;&amp;gt;Sign Out&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          {% else %}
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('signup') }}&amp;quot;&amp;gt;Sign Up&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ url_for('signin') }}&amp;quot;&amp;gt;Sign In&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          {% endif %}
        &amp;lt;/ul&amp;gt;
      &amp;lt;/nav&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/header&amp;gt;

    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
      {% block content %}
      {% endblock %}
    &amp;lt;/div&amp;gt;

  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;&lt;p&gt;Starting on line 17, we use Jinja2's &lt;code&gt;if...else&lt;/code&gt; syntax and the &lt;code&gt;session()&lt;/code&gt; object to check if the browser's cookie contains the '&lt;code&gt;email&lt;/code&gt;' key. If it does, then the user is signed in and therefore should see the "Profile" and "Sign Out" navigation links. Otherwise, the user is signed out and should see links to "Sign Up" and "Sign In".&lt;/p&gt;&lt;p&gt;Now give it a try! Check out how the navigation links appear and disappear by signing in and out of the app.&lt;/p&gt;&lt;p&gt;The last task remaining is a similar issue: when a user is signed in, we don't want him to be able to visit the signup and signin pages. It makes no sense for a signed in user to authenticate themselves again. If signed in users try to visit these pages, they should instead be redirected to their profile page. Open &lt;code&gt;routes.py&lt;/code&gt; and add the following piece of code to the beginning of the &lt;code&gt;signup()&lt;/code&gt; and &lt;code&gt;signin()&lt;/code&gt; functions:&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;if 'email' in session:
  return redirect(url_for('profile'))
&lt;/pre&gt;&lt;p&gt;Here's what your &lt;code&gt;routes.py&lt;/code&gt; file will look like after adding in that snippet of code:&lt;/p&gt;&lt;p&gt;&lt;code&gt;app/intro_to_flask/routes.py&lt;/code&gt;&lt;/p&gt;&lt;pre class="brush: python; title: ; notranslate"&gt;
@app.route('/signup', methods=['GET', 'POST'])
def signup():
  form = SignupForm()

  if 'email' in session:
    return redirect(url_for('profile')) 
.
.
.
@app.route('/signin', methods=['GET', 'POST'])
def signin():
  form = SigninForm()

  if 'email' in session:
    return redirect(url_for('profile'))  
  ...
&lt;/pre&gt;&lt;p&gt;And with that we're finished! Try visiting the the "signup" or "signin" pages while you are currently signed in, to test it out.&lt;/p&gt;&lt;p&gt;&amp;mdash; &lt;code&gt;Checkpoint: 20_visibility_control&lt;/code&gt; &amp;mdash;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;We've accomplished a lot in this article. We've taken our Flask app from being a simple Python module and turned it into a well organized application, capable of handling user authentication.&lt;/p&gt;&lt;p&gt;There are several directions in which you can take this app from here. Here are some ideas:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Let users sign in with an existing account, such as their Google account, by adding support for OpenID.&lt;/li&gt;&lt;li&gt;Give users the ability to update their account information, as well as delete their account.&lt;/li&gt;&lt;li&gt;Let users reset their password if they forget it.&lt;/li&gt;&lt;li&gt;Implement an authorization system.&lt;/li&gt;&lt;li&gt;Deploy to a production server. Note that when you deploy this app to production, you will need to implement SSL site-wide so that passwords and session tokens cannot be intercepted. If you deploy to Heroku, you can use their SSL certificate.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So go forth and continue to &lt;a
href="http://flask.pocoo.org/docs/"&gt;explore Flask&lt;/a&gt;, and build your next killer app! Thanks for reading.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=E4cf3iGOp7M:yXX_qU_dmvo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=E4cf3iGOp7M:yXX_qU_dmvo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=E4cf3iGOp7M:yXX_qU_dmvo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=E4cf3iGOp7M:yXX_qU_dmvo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=E4cf3iGOp7M:yXX_qU_dmvo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=E4cf3iGOp7M:yXX_qU_dmvo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=E4cf3iGOp7M:yXX_qU_dmvo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=E4cf3iGOp7M:yXX_qU_dmvo:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/E4cf3iGOp7M" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-signing-in-and-out/feed/</wfw:commentRss> <slash:comments>10</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/python-tutorials/intro-to-flask-signing-in-and-out/</feedburner:origLink></item> <item><title>Working With Data in Sails.js</title><link>http://feedproxy.google.com/~r/nettuts/~3/usUcBrdA3Cs/</link> <comments>http://net.tutsplus.com/tutorials/javascript-ajax/working-with-data-in-sails-js/#comments</comments> <pubDate>Wed, 12 Jun 2013 01:49:56 +0000</pubDate> <dc:creator>Gabriel Manricks</dc:creator> <category><![CDATA[JavaScript & AJAX]]></category> <category><![CDATA[Tutorials]]></category> <category><![CDATA[sails.js data]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=31525</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=31525&amp;c=1136919021' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=31525&amp;c=1136919021' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;&lt;a
href="http://sailsjs.org/"&gt;Sails.js&lt;/a&gt; is an up and coming Node.js framework, with a focus on freedom and smart defaults. In this article we&amp;#8217;ll take a look at some of the data features Sails provides out-of-the-box, for easily making complex apps.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-31525"&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Why Sails Is Different Than Other Frameworks&lt;/h2&gt;&lt;p&gt;The reason to choose Sails is best put by the Sails creator, &lt;a
href='http://balderdash.co/' title='Mike McNeil'&gt;Mike McNeil&lt;/a&gt;, &amp;quot;Sails was created out of necessity&amp;quot;. Many frameworks you see around, are built almost for the academic side of things, these frameworks usually foster best practices, and create a platform for developers to create things faster, or better.&lt;/p&gt;&lt;p&gt;Sails on the other hand, was created for production, it&amp;#8217;s not trying to feed you a new syntax or platform, it&amp;#8217;s a solid base, meant for creating &amp;apos;client-work&amp;apos; with speed. The contrast may be subtle, but there are a few distinct differences.&lt;/p&gt;&lt;p&gt;To illustrate what I&amp;#8217;m referring to, let&amp;apos;s take a look at &lt;a
href='http://meteor.com' title='Meteor'&gt;Meteor&lt;/a&gt;. Meteor is probably the leading JS platform around today, but it&amp;#8217;s a prime example of a framework, for the sake of a framework. Now this is not a bad thing, I am a big supporter of Meteor, what I mean is, they set out to build a framework and they did a good job at it, Mike on the other hand set out to make client-work faster. Sails is just a means to reach an end.&lt;/p&gt;&lt;p&gt;In Meteor, pretty much everything is abstracted away and you use JavaScript plus the Meteor API to code everything. Whereas Sails is not meant to be a new platform, so nothing is hidden.&lt;/p&gt;&lt;p&gt;It rests on top of Socket.io and the popular Express framework, and you have access to them in their entirety, natively. Are you beginning to see the difference?&lt;/p&gt;&lt;p&gt;Furthermore, since Sails is geared for production first, it&amp;#8217;s built with multiple options for scaling and security.&lt;/p&gt;&lt;p&gt;There is alot to talk about, but in this article I would like to focus on how Sails handles data, and how you can leverage some of Sails&amp;apos; more advanced features to perform some really cool actions.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Installation&lt;/h2&gt;&lt;p&gt;Just in case you do not have Sails intalled yet, you can do so via &lt;a
href='http://nodejs.org/download/' title='NPM + Node.JS'&gt;NPM&lt;/a&gt; by running:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;
sudo npm install -g sails
&lt;/pre&gt;&lt;hr
/&gt;&lt;h2&gt;Socket.io &amp;amp; Express&lt;/h2&gt;&lt;p&gt;Now let&amp;apos;s talk a little bit about &lt;a
href='http://socket.io/' title='Socket.io'&gt;Socket.io&lt;/a&gt; and &lt;a
href='http://expressjs.com/'&gt;Express&lt;/a&gt; before we get into Sails. There&amp;#8217;s a good premium series on &lt;a
href='https://tutsplus.com/course/building-web-apps-in-node-and-express/' title='Express Series'&gt;Express&lt;/a&gt; by &lt;a
href='http://andrewburgess.ca/' title='Andrew Burgess'&gt;Andrew Burgess&lt;/a&gt; if you&amp;#8217;re interested, but I&amp;apos;ll run through the relevant basics of both of these libraries here:&lt;/p&gt;&lt;h3&gt;Socket.io&lt;/h3&gt;&lt;p&gt;Socket.io is a pub/sub library, which is run on both the server and on the client, and it allows them to speak via web sockets.&lt;/p&gt;&lt;p&gt;A brief example could look something like this:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
//Code For Server
var io = require(&amp;quot;socket.io&amp;quot;);
io.sockets.on(&amp;quot;connection&amp;quot;, function (sock) {
    sock.emit(&amp;quot;welcomeMessage&amp;quot;, { hello: &amp;quot;world&amp;quot; });
}
io.listen(80);
&lt;/pre&gt;&lt;p&gt;This code starts out by requiring the &lt;code&gt;socket.io&lt;/code&gt; library, listening for a connection, and then when another socket connects, it will send it a message, addressed to the &lt;code&gt;welcomeMessage&lt;/code&gt; event, and finally passing along some JSON.&lt;/p&gt;&lt;p&gt;Next, on the client you would write something like:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
//Code For Client
var sock = io.connect('http://localhost');
sock.on('welcomeMessage', function (json) {
    //Handle Event Received
});
&lt;/pre&gt;&lt;p&gt;Here we&amp;#8217;re connecting to the server and listening for that &lt;code&gt;welcomeMessage&lt;/code&gt; event we just created. As you can see it&amp;apos;s a fairly simple publish / subscribe server, which is bidirectional (the client could emit messages for the server as well).&lt;/p&gt;&lt;p&gt;Now let&amp;apos;s take a look at Express:&lt;/p&gt;&lt;h3&gt;Express&lt;/h3&gt;&lt;p&gt;The simplest form of an Express route could be something like:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
app.get('/users', function(req, res) {
    res.send(&amp;quot;Hello from '/users' !&amp;quot;);
});
&lt;/pre&gt;&lt;p&gt;This defines a simple route, so that when a user goes to your site&amp;apos;s address and tries to access the &lt;code&gt;/users&lt;/code&gt; page, they will be presented with the message &lt;code&gt;&amp;quot;Hello from &amp;apos;/users&amp;apos; !&amp;quot;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So Express is a framework for handling HTTP requests and Socket.io is a websocket communications library. What the Sails team have done though, is map all Express routes to Socket.io internally. What this means is, you can call any of the HTTP routes through web sockets.&lt;/p&gt;&lt;p&gt;Now that&amp;#8217;s pretty cool! But, there is still one piece of the puzzle missing and that is the Sails Blueprints.&lt;/p&gt;&lt;p&gt;Sails allows you to generate models just like in other frameworks, the difference is, Sails can also generate a production ready RESTfull API to go with them. This means if you generate a model named &amp;apos;&lt;code&gt;users&lt;/code&gt;&amp;apos; you can immediately run RESTfull queries on the &amp;apos;&lt;code&gt;/users&lt;/code&gt;&amp;apos; resource without any coding necessary.&lt;/p&gt;&lt;p&gt;If you are new to RESTful APIs, it&amp;#8217;s just a way of accessing data, to where CRUD operations are mapped to various HTTP methods.&lt;/p&gt;&lt;p&gt;So a &lt;code&gt;GET&lt;/code&gt; request to &amp;apos;&lt;code&gt;/users&lt;/code&gt;&amp;apos; will get all of the users, a &lt;code&gt;POST&lt;/code&gt; request will create a new user, etc.&lt;/p&gt;&lt;p&gt;So what does all of this mean?&lt;/p&gt;&lt;p&gt;It means we have a full RESTfull API, mapped to Socket.io via Sails, without writing a single line of code!&lt;/p&gt;&lt;p&gt;But why are sockets better at retrieving data then an Ajax request? Well, besides being a leaner protocol, sockets stay open for bidirectional communication, and Sails has taken advantage of this. Not only will Sails pass you the data, but it will automatically subscribe you to updates on that database, and whenever something gets added, removed, or updated, your client will receive a notification via the web socket, letting you know about it.&lt;/p&gt;&lt;p&gt;This is why Sails is so awesome!&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Sails + Backbone&lt;/h2&gt;&lt;p&gt;The next topic I&amp;#8217;d like to cover is Backbone integration, because if you aren&amp;apos;t using a JavaScript framework, you are doing it wrong.&lt;/p&gt;&lt;p&gt;With this in mind, Sails and Backbone are the perfect pair. Backbone, like Sails, is extremely unobtrusive, all of its features are available, capable of being overridden, and optional.&lt;/p&gt;&lt;p&gt;If you have used Backbone before then you may know it connects natively with REST APIs, so out of the box, you can sync the data on the front-end with your Sails application.&lt;/p&gt;&lt;p&gt;But enough talk for now, let&amp;apos;s take a look at all of this in action by creating a basic chat application. To get started, open up a terminal window and type:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;
sails new ChatApp
cd ChatApp
sails generate model users
sails generate model messages
sails generate controller messages
sails generate controller main
&lt;/pre&gt;&lt;p&gt;This will create a new app and generate some files for us. You can see from above, there are two different resources that you can generate; models and controllers. If you are familiar with the MVC design pattern, then you should know what these are, but in short, models are your data and controllers hold your logic code. So we are going to need two collections, one to hold the users, and one for the messages.&lt;/p&gt;&lt;p&gt;Next, for the controllers, we need one to handle the page routes, I called it &amp;apos;&lt;code&gt;main&lt;/code&gt;&amp;apos;, then we have a second controller named &amp;apos;&lt;code&gt;messages&lt;/code&gt;&amp;apos;. Now you might wonder why I created a controller with the same name as our &lt;code&gt;messages&lt;/code&gt; model? Well, if you remember, I said that Sails can create a REST API for you. What happens is, by creating a blank controller with the same name as a model, Sails will know to fall back and build a REST API for the corresponding resource.&lt;/p&gt;&lt;p&gt;So, we&amp;#8217;ve created a controller for our &lt;code&gt;messages&lt;/code&gt; model, but there&amp;#8217;s no need to create one for the users model, so I just left it out. And that&amp;#8217;s all there is to creating models and controllers.&lt;/p&gt;&lt;p&gt;Next, let&amp;#8217;s setup some routes.&lt;/p&gt;&lt;h3&gt;Routes&lt;/h3&gt;&lt;p&gt;Routes are always a safe place to begin, because you usually have a good idea of which pages are going to be made.&lt;/p&gt;&lt;p&gt;So open up the &lt;code&gt;routes.js&lt;/code&gt; file which is in the &lt;code&gt;config&lt;/code&gt; folder, it may look a little overwhelming at first, but if you remove all of the comments and add the in the following routes, you will be left with something like this:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
module.exports.routes = {
    '/' : {
         controller: 'main',
         action: 'index'
    },
    '/signup' : {
         controller: 'main',
         action: 'signup'
    },
    '/login' : {
         controller: 'main',
         action: 'login'
    },
    '/chat' : {
         controller: 'main',
         action: 'chat'
    }
};
&lt;/pre&gt;&lt;p&gt;We have a home page, a chat page, and then two pages for handling both the login and signup pages. I put them all in the same controller, but in Sails, you can create as many controllers as you&amp;#8217;d like.&lt;/p&gt;&lt;h3&gt;Models&lt;/h3&gt;&lt;p&gt;Next, let&amp;apos;s take a look at the generated &lt;code&gt;messages&lt;/code&gt; model which can be located at &amp;quot;&lt;code&gt;api &amp;gt; models &amp;gt; Messages.js&lt;/code&gt;&amp;quot;. We need to add the necessary columns to our model. Now this is not absolutely necessary, but it will create some helper functions for us that we can use:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
//Messages Model  
module.exports = {
    attributes  : {
        userId: 'INT',
        username: 'STRING',
        message: 'STRING'      
    }
};
&lt;/pre&gt;&lt;p&gt;For the &lt;code&gt;messages&lt;/code&gt; model, we start with the &lt;code&gt;id&lt;/code&gt; of the user that this message belongs to, a &lt;code&gt;username&lt;/code&gt; so we won&amp;apos;t have to query this separately, and then the actual &lt;code&gt;message&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Now let&amp;apos;s fill in the user&amp;apos;s model:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
//Users Model 
module.exports = {
    attributes  : {
         username: 'STRING',
         password: 'STRING'      
    }
};
&lt;/pre&gt;&lt;p&gt;And that&amp;#8217;s it, we have just the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; attributes. The next step is to create our route functions inside of the &lt;code&gt;MainController&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;Controllers&lt;/h3&gt;&lt;p&gt;So open up the &lt;code&gt;MainController&lt;/code&gt;, which can be found at &amp;quot;&lt;code&gt;api &amp;gt; controllers &amp;gt; MainController.js&lt;/code&gt;&amp;quot;. Let&amp;apos;s begin by creating a function for each of the routes we defined above:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var MainController = {
    index: function (req, res) {
        
    },
    signup: function (req, res) {
        
    },
    login: function (req, res) {
        
    },
    chat: function (req, res) {
        
    }
};
module.exports = MainController;   
&lt;/pre&gt;&lt;p&gt;If you&amp;#8217;re familiar with Express, then you&amp;#8217;ll be happy to see that these functions are standard Express route functions. They receive two variables, &lt;code&gt;req&lt;/code&gt; for the HTTP request and &lt;code&gt;res&lt;/code&gt; to create the response.&lt;/p&gt;&lt;p&gt;Following the MVC pattern, Sails offers a function for rendering views. The home page doesn&amp;apos;t need anything special, so let&amp;apos;s just render the view.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
index: function (req, res) {
    res.view();
},
&lt;/pre&gt;&lt;p&gt;Sails leans more toward convention over configuration, so when you call &lt;code&gt;res.view();&lt;/code&gt; Sails will look for a view file (with a &lt;code&gt;.ejs&lt;/code&gt; extension by default) using the following pattern: &amp;apos;&lt;code&gt;views &amp;gt; controllerName &amp;gt; methodName.ejs&lt;/code&gt;&amp;apos;. So for this call, it will search for &amp;apos;&lt;code&gt;views &amp;gt; main &amp;gt; index.ejs&lt;/code&gt;&amp;apos;. It&amp;apos;s also worth noting, these views only contain the view specific parts of the page. If you take a look at &amp;apos;&lt;code&gt;views &amp;gt; layout.ejs&lt;/code&gt;&amp;apos;, you will see a call in the middle for &lt;code&gt;&amp;lt;%- body %&amp;gt;&lt;/code&gt;, this is where your view file will be inserted. By default it uses this &amp;apos;&lt;code&gt;layout.ejs&lt;/code&gt;&amp;apos; file, but you can use other layout files just by passing the layout name into the &lt;code&gt;res.view()&lt;/code&gt; function, under the property named &amp;apos;layout&amp;apos;. For example: &amp;apos;&lt;code&gt;res.view( { layout: &amp;quot;other.ejs&amp;quot; } );&lt;/code&gt;&amp;apos;.&lt;/p&gt;&lt;p&gt;I&amp;#8217;m going to use the default layout file with a small adjustment, I&amp;#8217;m going to add jQuery, Backbone, and Underscore. So in the &amp;apos;&lt;code&gt;layout.ejs&lt;/code&gt;&amp;apos; file right before the closing &lt;code&gt;&amp;lt;/head&amp;gt;&lt;/code&gt; tag, add the following lines:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
&amp;lt;script src=&amp;quot;//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;p&gt;With that in place we&amp;#8217;re now ready to create the home page.&lt;/p&gt;&lt;h3&gt;The Home Page&lt;/h3&gt;&lt;p&gt;Let&amp;#8217;s create a new folder inside of the &lt;code&gt;views&lt;/code&gt; folder named &lt;code&gt;main&lt;/code&gt;, and inside of our new &lt;code&gt;main&lt;/code&gt; folder, we&amp;#8217;ll create a new file named &amp;apos;index.ejs&amp;apos;.&lt;/p&gt;&lt;p&gt;Inside the file let&amp;apos;s just create a login and signup form:&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;h1&amp;gt;Code Chat&amp;lt;/h1&amp;gt;
&amp;lt;div&amp;gt;
    &amp;lt;h3&amp;gt;Login&amp;lt;/h3&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;loginName&amp;quot; placeholder=&amp;quot;name&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;password&amp;quot; id=&amp;quot;loginPassword&amp;quot; placeholder=&amp;quot;password&amp;quot; /&amp;gt;
    &amp;lt;button id=&amp;quot;loginButton&amp;quot;&amp;gt;Login&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;
    &amp;lt;h3&amp;gt;Signup&amp;lt;/h3&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;signupName&amp;quot; placeholder=&amp;quot;name&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;password&amp;quot; id=&amp;quot;signupPassword&amp;quot; placeholder=&amp;quot;password&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;password&amp;quot; id=&amp;quot;signupConfirmPassword&amp;quot; placeholder=&amp;quot;confirm password&amp;quot; /&amp;gt;
    &amp;lt;button id=&amp;quot;signupButton&amp;quot;&amp;gt;Signup&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;Pretty simple, just the essentials.&lt;/p&gt;&lt;h3&gt;The Login and Signup Areas&lt;/h3&gt;&lt;p&gt;Next we need to add a little JS to get this communicating with the server. Now this won&amp;#8217;t be Sails specific, we are just going to send an AJAX request via jQuery to the Sails server.&lt;/p&gt;&lt;p&gt;This code can either be included on the page itself or loaded in via a separate JS file. For the sake of convenience, I&amp;#8217;m just going to put it at the bottom of the same page:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
&amp;lt;script&amp;gt;
    $(&amp;quot;#loginButton&amp;quot;).click(function(){
        var username = $(&amp;quot;#loginName&amp;quot;).val();
        var password = $(&amp;quot;#loginPassword&amp;quot;).val();
        if (username &amp;amp;&amp;amp; password) {
            $.post(
                '/login',
                {username: username, password:password},
                function () {
                    window.location = &amp;quot;/chat&amp;quot;;
                }
            ).fail(function(res){
                alert(&amp;quot;Error: &amp;quot; + res.getResponseHeader(&amp;quot;error&amp;quot;));
            });
        } else {
            alert(&amp;quot;A username and password is required&amp;quot;);
        }
    });
&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;p&gt;This is all just standard JS and jQuery, we&amp;#8217;re listening for the click event on the login button, making sure the username and password fields are filled in, and posting the data to the &amp;apos;&lt;code&gt;/login&lt;/code&gt;&amp;apos; route. If the login is successful, we redirect the user to the chat page, otherwise we will display the error returned by the server.&lt;/p&gt;&lt;p&gt;Next, let&amp;apos;s create the same thing for the signup area:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
$(&amp;quot;#signupButton&amp;quot;).click(function(){
    var username = $(&amp;quot;#signupName&amp;quot;).val();
    var password = $(&amp;quot;#signupPassword&amp;quot;).val();
    var confirmPassword = $(&amp;quot;#signupConfirmPassword&amp;quot;).val();
    if (username &amp;amp;&amp;amp; password) {
        if (password === confirmPassword) {
            $.post(
                '/signup',
                {username: username, password:password},
                function () {
                    window.location = &amp;quot;/chat&amp;quot;;
                }
            ).fail(function(res){
                alert(&amp;quot;Error: &amp;quot; + res.getResponseHeader(&amp;quot;error&amp;quot;));
            });
        } else {
            alert(&amp;quot;Passwords don't match&amp;quot;);
        }   
    } else {
        alert(&amp;quot;A username and password is required&amp;quot;);
    }
}); 
&lt;/pre&gt;&lt;p&gt;This code is almost identical, so much so, that you can probably just abstract the whole Ajax part out into its own function, but for this tutorial it&amp;apos;s fine.&lt;/p&gt;&lt;p&gt;Now we need to go back to our &amp;apos;&lt;code&gt;MainController&lt;/code&gt;&amp;apos; and handle these two routes, but before we do that, I want to install a Node module. We&amp;#8217;re going to need to hash the password, as plain text passwords are &lt;em&gt;not&lt;/em&gt; a good thing, not even for demonstration! I found a nice module named &lt;a
href='https://npmjs.org/package/password-hash' title='Password-Hash NPM Module'&gt;&amp;apos;password-hash&amp;apos;&lt;/a&gt; by &lt;a
href='https://twitter.com/bitprobe' title='David Wood'&gt;David Wood&lt;/a&gt; which will work out nicely.&lt;/p&gt;&lt;p&gt;To install it, just go to the root of your Sails app, from within your terminal and type: &lt;code&gt;npm install password-hash&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Once that installs, let&amp;apos;s open the &lt;code&gt;MainController&lt;/code&gt; and implement the two needed routes. Let&amp;#8217;s start with &lt;code&gt;signup&lt;/code&gt;:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
signup: function (req, res) {
        var username = req.param(&amp;quot;username&amp;quot;);
        var password = req.param(&amp;quot;password&amp;quot;);
        
        Users.findByUsername(username).done(function(err, usr){
            if (err) {
                res.send(500, { error: &amp;quot;DB Error&amp;quot; });
            } else if (usr) {
                res.send(400, {error: &amp;quot;Username already Taken&amp;quot;});
            } else {
                var hasher = require(&amp;quot;password-hash&amp;quot;);
                password = hasher.generate(password);
                
                Users.create({username: username, password: password}).done(function(error, user) {
                if (error) {
                    res.send(500, {error: &amp;quot;DB Error&amp;quot;});
                } else {
                    req.session.user = user;
                    res.send(user);
                }
            });
        }
    });
}
&lt;/pre&gt;&lt;p&gt;It&amp;apos;s a bit verbose, but all we&amp;#8217;re doing here is reading the username and password from the POST request and making sure the username is not already taken. You can see I&amp;#8217;m also using the password-hasher we just installed, it&amp;apos;s super simple to use, just pass the password into the generate method and it will hash it using a random salt.&lt;/p&gt;&lt;p&gt;It&amp;apos;s also worth mentioning, that at every possible location where we may run into an error or issue, we&amp;#8217;re sending back an HTTP error code and returning a message via a custom header named &amp;apos;&lt;code&gt;error&lt;/code&gt;&amp;apos; which, if you remember, we&amp;#8217;re displaying in an alert message on the index page.&lt;/p&gt;&lt;p&gt;Another noteworthy point, is the fact that we&amp;#8217;re using a &amp;apos;magic&amp;apos; function named &amp;apos;&lt;code&gt;findByUsername&lt;/code&gt;&amp;apos;, this is made possible because we have a &lt;code&gt;username&lt;/code&gt; column inside of our Users model.&lt;/p&gt;&lt;p&gt;Finally, at the bottom you can see if everything went well, we&amp;#8217;re storing the user in a session variable and returning it with a default status code of 200, which will tell jQuery that the AJAX request was successful.&lt;/p&gt;&lt;p&gt;Next, let&amp;apos;s write the login function:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
login: function (req, res) {
    var username = req.param(&amp;quot;username&amp;quot;);
    var password = req.param(&amp;quot;password&amp;quot;);
    
    Users.findByUsername(username).done(function(err, usr) {
        if (err) {
            res.send(500, { error: &amp;quot;DB Error&amp;quot; });
        } else {
            if (usr) {
                var hasher = require(&amp;quot;password-hash&amp;quot;);
                if (hasher.verify(password, usr.password)) {
                    req.session.user = usr;
                    res.send(usr);
                } else {
                    res.send(400, { error: &amp;quot;Wrong Password&amp;quot; });
                }
            } else {
                res.send(404, { error: &amp;quot;User not Found&amp;quot; });
            }
        }
    });
}
&lt;/pre&gt;&lt;p&gt;Again, this is very similar to the previous &lt;code&gt;signup&lt;/code&gt; function, we&amp;#8217;re searching for a user with the same username that was posted from the form and if it finds one, we check if the password matches using the hasher&amp;#8217;s &lt;code&gt;verify&lt;/code&gt; method. The reason we can&amp;apos;t just hash the password again and pass it into the models &lt;code&gt;find&lt;/code&gt; function is because the hasher uses a random salt, so if we hashed the password again it would be equal to something else.&lt;/p&gt;&lt;p&gt;The rest of the code is the same; if everything checks out, we store the user in a session and return it, otherwise we send back an error message.&lt;/p&gt;&lt;p&gt;The login system is now complete and we&amp;#8217;re finally able to move on to building the chat feature.&lt;/p&gt;&lt;h3&gt;Building the Chat Feature&lt;/h3&gt;&lt;p&gt;Since we&amp;#8217;ll be using Backbone for getting the messages, the actual route function will be very simple. Here&amp;#8217;s the complete chat function:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
chat: function (req, res) {
    if (req.session.user) {
        res.view({username: req.session.user.username});
    } else {
        res.redirect('/');
    }
}
&lt;/pre&gt;&lt;p&gt;We start off by checking if the user is logged in or not, if this checks out, then it will load the view, passing it the username that was in the session, otherwise we just redirect to the home page.&lt;/p&gt;&lt;p&gt;Now let&amp;#8217;s create a new view named &amp;apos;&lt;code&gt;chat.ejs&lt;/code&gt;&amp;apos; inside of the &lt;code&gt;main&lt;/code&gt; folder. Open it up and let&amp;apos;s create a simple form to post new messages and a &lt;code&gt;div&lt;/code&gt; container for displaying all of them.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;h2&amp;gt;Welcome &amp;lt;%= username %&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div id=&amp;quot;newMessageForm&amp;quot;&amp;gt;
    &amp;lt;textarea id=&amp;quot;message&amp;quot; placeholder=&amp;quot;Enter your message here:&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
    &amp;lt;button id=&amp;quot;postMessageButton&amp;quot;&amp;gt;Add Message&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;messagesContainer&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;So for this view, we just used some pretty standard HTML. The only thing that may require some explanation is the &lt;code&gt;&amp;lt;%= username %&amp;gt;&lt;/code&gt; code, this style of coding is not specific to Sails, it&amp;#8217;s actually the syntax for EJS. This syntax is very similar to PHP&amp;#8217;s short tags. &lt;code&gt;&amp;lt;%&lt;/code&gt; is the equivalent of &lt;code&gt;&amp;lt;?&lt;/code&gt; in PHP and &lt;code&gt;&amp;lt;%=&lt;/code&gt; is the same as &lt;code&gt;&amp;lt;?=&lt;/code&gt;. The first snippet of EJS allows you to integrate standard JS code on the page, whereas the second prints out the code within. Here we&amp;#8217;re just printing out the username that we passed in from the controller.&lt;/p&gt;&lt;p&gt;The rest of our chat feature will be all JavaScript. To get started, let&amp;apos;s take a look at how you would write the chat functionality using standard Backbone, and then we&amp;#8217;ll see how to take advantage of web sockets.&lt;/p&gt;&lt;p&gt;At the bottom of the page, add the following JS:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
&amp;lt;script&amp;gt;
    var MessageModel = Backbone.Model.extend({
        urlRoot: '/messages',
    });

    var MessageCollection = Backbone.Collection.extend({
        url: '/messages',
        model: MessageModel,
    });

    var messages = new MessageCollection();
    messages.fetch();

    $(&amp;quot;#postMessageButton&amp;quot;).click(function(){
        var messageText = $(&amp;quot;#message&amp;quot;).val();
        messages.create({message: messageText}, {wait: true});
        $(&amp;quot;#message&amp;quot;).val(&amp;quot;&amp;quot;);
    });
&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;p&gt;Since Sails automatically creates an API that Backbone understands natively, no extra server code has to be written, it doesn&amp;#8217;t get much easier than that. This is what I was talking about when I said that Sails was not made to be a &amp;apos;framework&amp;apos;. It doesn&amp;apos;t try to make you use its own syntax, it was made to get things done and as you can see, it delivers.&lt;/p&gt;&lt;p&gt;To test it out, open up a terminal window and navigate to your Sails app folder, then type &amp;apos;&lt;code&gt;sails lift&lt;/code&gt;&amp;apos; to start it up. By default it will launch to &lt;code&gt;http://localhost:1337&lt;/code&gt;. Now just signup and post a few messages.&lt;/p&gt;&lt;p&gt;To see your posted messages you can &lt;code&gt;console.log&lt;/code&gt; the messages variable, or look at it inside of the browser&amp;#8217;s console. Now the next thing we should implement is a view so we can see the posted messages in the browser.&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
_.templateSettings = {
    interpolate : /\{\{(.+?)\}\}/g
};
var MessagesView = Backbone.View.extend({
    el: '#messagesContainer',
    initialize: function () {
        this.collection.on('add', this.render, this);
        this.render();
    },
    template: _.template(&amp;quot;&amp;lt;div&amp;gt;&amp;lt;p&amp;gt;{{ message }}&amp;lt;/p&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;),
        render: function () {
            this.$el.html(&amp;quot;&amp;quot;);
            this.collection.each(function(msg){
                this.$el.append(this.template(msg.toJSON()));
            }, this)
    }
});

var mView = new MessagesView({collection: messages});
&lt;/pre&gt;&lt;p&gt;We start off by defining a view, attaching it to the div that we created earlier, then we add an event handler on the collection to re-render the div every time a new model gets added to the collection.&lt;/p&gt;&lt;p&gt;You can see at the top, I had to change the default Underscore settings from using the EJS syntax inside of the templates, to instead, use Mustache&amp;#8217;s syntax. This is because the page is already an EJS document, so it would be processed out on the server and not in Underscore.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: I didn&amp;apos;t come up with the Regex for this, that credit goes to the &lt;a
href='http://underscorejs.org/#template' title='Underscore Template Docs'&gt;Underscore docs&lt;/a&gt; itself.&lt;/p&gt;&lt;p&gt;Lastly, at the bottom you can see we created a new instance of this view, passing it the collection variable.&lt;/p&gt;&lt;p&gt;If all went well, you should now see your messages in the browser, and it should update whenever you create a new post.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Sails Policies&lt;/h2&gt;&lt;p&gt;Now you may have noticed that we&amp;#8217;re not setting the &lt;code&gt;userId&lt;/code&gt; or the &lt;code&gt;username&lt;/code&gt; when we submit the posts, and this is for security purposes.&lt;/p&gt;&lt;p&gt;You don&amp;apos;t want to put this kind of control on the client side. If all someone has to do is modify a JavaScript variable to control another user&amp;#8217;s account, you&amp;#8217;ll have a major problem.&lt;/p&gt;&lt;p&gt;So, how should you handle this? Well, with policies of course.&lt;/p&gt;&lt;p&gt;Policies are basically middleware, which run before the actual web request, where you can stop, modify, or even redirect the request, as needed.&lt;/p&gt;&lt;p&gt;For this app, let&amp;apos;s create a policy for our messages. Policies are applied to controllers, so they can even be run on normal pages, but for this tutorial let&amp;apos;s just stick with one for our &lt;code&gt;messages&lt;/code&gt; Model.&lt;/p&gt;&lt;p&gt;Create a file named &amp;apos;MessagesPolicy.js&amp;apos; inside the &amp;apos;&lt;code&gt;api &amp;gt; policies&lt;/code&gt;&amp;apos; folder, and enter the following:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
module.exports = function (req, res, next) {
    if (req.session.user) {
        var action = req.param('action');
        if (action == &amp;quot;create&amp;quot;) {
            req.body.userId = req.session.user.id;
            req.body.username = req.session.user.username;
        }
        next();
    } else {
        res.send(&amp;quot;You Must Be Logged In&amp;quot;, 403);
    }
};
&lt;/pre&gt;&lt;p&gt;So, what&amp;#8217;s going on here? You can see this function resembles a normal route function, the difference though is the third parameter, which will call the next middleware in the stack. If you&amp;#8217;re new to the idea of middleware, you can think of it like a Russian nesting doll. Each layer gets the request, along with the response variables and they can modify them as they see fit. If they pass all of the requirements, the layer can pass it further in, until it reaches the center, which is the route function.&lt;/p&gt;&lt;p&gt;So here we are, checking if the user is logged in, if the user isn&amp;apos;t, we display a 403 error and the request ends here. Otherwise, (i.e. the user is logged in) we call &lt;code&gt;next();&lt;/code&gt; to pass it on. In the middle of the above code, is where we inject some post variables. We&amp;#8217;re applying this to all calls on the &amp;apos;messages&amp;apos; controller (basically the API), so we get the action and check if this request is trying to create a new message, in which case we add the post fields for the user&amp;apos;s &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;username&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Next, open up the &lt;code&gt;policies.js&lt;/code&gt; file which is in the config folder, and add in the policy that we just created. So your file should look like this:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
module.exports.policies = { 
    '*': true,
    'messages': 'MessagesPolicy'
};
&lt;/pre&gt;&lt;p&gt;With this put in to place, we&amp;#8217;ll need to delete all of the old records, as they do not have these new pieces of information. So, close the Sails server (ctrl-c) and in the same terminal window type: &lt;code&gt;rm -r .tmp&lt;/code&gt; to remove the temporary database giving us a clean slate.&lt;/p&gt;&lt;p&gt;Next, let&amp;apos;s add the username to the actual posts, so in the &amp;apos;chat.ejs&amp;apos; change the template to:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
template: _.template(&amp;quot;&amp;lt;div&amp;gt;&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;{{ username }}: &amp;lt;/b&amp;gt;{{ message }}&amp;lt;/p&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;),
&lt;/pre&gt;&lt;p&gt;Restart the Sails server (again using &lt;code&gt;sails lift&lt;/code&gt;) and signup another new user to test it out. If everything is working correctly, you should be able to add messages and see your name in the post.&lt;/p&gt;&lt;p&gt;At this point we have a pretty good setup, we fetch the post automatically using Backbone and the API, plus we have some basic security in place. The problem is, it won&amp;apos;t update when other people post messages. Now you could solve this by creating a JavaScript interval and poll for updates, but we can do better.&lt;/p&gt;&lt;h3&gt;Leveraging Websockets&lt;/h3&gt;&lt;p&gt;I mentioned earlier that Sails leverages websockets&amp;#8217; bidirectional abilities to post updates on the subscribed data. Using these updates, we can listen for new additions to the messages table and update the collection accordingly.&lt;/p&gt;&lt;p&gt;So in the &lt;code&gt;chat.ejs&lt;/code&gt; file, let&amp;apos;s create a new kind of collection; a SailsCollection:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var SailsCollection = Backbone.Collection.extend({
    sailsCollection: &amp;quot;&amp;quot;,
    socket: null,
    sync: function(method, model, options){
        var where = {};
        if (options.where) {
            where = {
                where: options.where
            }
        }       
        if(typeof this.sailsCollection === &amp;quot;string&amp;quot; &amp;amp;&amp;amp; this.sailsCollection !== &amp;quot;&amp;quot;) {
            this.socket = io.connect();
            this.socket.on(&amp;quot;connect&amp;quot;, _.bind(function(){
                this.socket.request(&amp;quot;/&amp;quot; + this.sailsCollection, where, _.bind(function(users){
                    this.set(users);
                }, this));
    
                this.socket.on(&amp;quot;message&amp;quot;, _.bind(function(msg){
                    var m = msg.uri.split(&amp;quot;/&amp;quot;).pop();
                    if (m === &amp;quot;create&amp;quot;) {
                        this.add(msg.data);
                    } else if (m === &amp;quot;update&amp;quot;) {
                        this.get(msg.data.id).set(msg.data);
                    } else if (m === &amp;quot;destroy&amp;quot;) {
                        this.remove(this.get(msg.data.id));
                    }
                }, this));
            }, this));
        } else {
            console.log(&amp;quot;Error: Cannot retrieve models because property 'sailsCollection' not set on the collection&amp;quot;);
        }
    }
});
&lt;/pre&gt;&lt;p&gt;Now it may be long, but it&amp;apos;s actually very simple, let&amp;apos;s walk through it. We start off by adding two new properties to the Collection object, one to hold the name of the Sails &amp;apos;model&amp;apos; and one to hold the web socket. Next, we modify the &lt;code&gt;sync&lt;/code&gt; function, if you&amp;#8217;re familiar with Backbone, then you&amp;#8217;ll know that this is the function which interfaces with the server when you call things such as &lt;code&gt;fetch&lt;/code&gt;. Usually, it fires off Ajax requests, but we&amp;#8217;re going to customize it for socket communication.&lt;/p&gt;&lt;p&gt;Now, we&amp;#8217;re not using most of the functionality that the &lt;code&gt;sync&lt;/code&gt; function offers, mainly because we haven&amp;apos;t added the ability for users to update or delete messages, but just to be complete, I will include them within the function definition.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s take a look at the first part of the &lt;code&gt;sync&lt;/code&gt; function:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var where = {};
if (options.where) {
    where = {
        where: options.where
    }
}   
&lt;/pre&gt;&lt;p&gt;This code first checks if any &amp;apos;&lt;code&gt;where&lt;/code&gt;&amp;apos; clauses were sent through, this would let you do things like: &lt;code&gt;messages.fetch({ where : { id: 4 } });&lt;/code&gt; to only fetch rows where the id equals four.&lt;/p&gt;&lt;p&gt;After that, we then have some code that makes sure the &amp;apos;&lt;code&gt;sailsCollection&lt;/code&gt;&amp;apos; property has been set, otherwise we log an error message. Afterwards, we create a new socket and connect to the server, listening for the connection with the &lt;code&gt;on(&amp;apos;connect&amp;apos;)&lt;/code&gt; event.&lt;/p&gt;&lt;p&gt;Once connected, we request the index of the &amp;apos;&lt;code&gt;sailsCollection&lt;/code&gt;&amp;apos; specified to pull in the current list of models. When it receives the data, we use the collection&amp;apos;s &lt;code&gt;set&lt;/code&gt; function to initially set the models.&lt;/p&gt;&lt;p&gt;Alright, now so far, we have the equivalent of the standard &lt;code&gt;fetch&lt;/code&gt; command. The next block of code is where the push notifications happen:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
this.socket.on(&amp;quot;message&amp;quot;, _.bind(function(msg){
    var m = msg.uri.split(&amp;quot;/&amp;quot;).pop();
    if (m === &amp;quot;create&amp;quot;) {
        this.add(msg.data);
    } else if (m === &amp;quot;update&amp;quot;) {
        this.get(msg.data.id).set(msg.data);
    } else if (m === &amp;quot;destroy&amp;quot;) {
        this.remove(this.get(msg.data.id));
    }
}, this));
&lt;/pre&gt;&lt;p&gt;Now the action that&amp;#8217;s being performed (whether we&amp;#8217;re creating, updating, or destroying a message) can be found inside of the actual &lt;code&gt;msg&lt;/code&gt;, which is then inside of the &lt;code&gt;uri&lt;/code&gt;. To get the action, we split the URI on forward slashes (&amp;apos;/&amp;apos;) and grab just the last segment using the &lt;code&gt;pop&lt;/code&gt; function. We then try to match it up with the three possible actions of &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, or &lt;code&gt;destroy&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The rest is standard Backbone, we either add, edit, or remove the specified model. With our new class almost complete, all that&amp;#8217;s left to do is change the current &lt;code&gt;MessageCollection&lt;/code&gt;. Instead of extending the Backbone collection, it needs to extend our new collection, like so:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
var MessageCollection = SailsCollection.extend({
    sailsCollection: 'messages',
    model: MessageModel
});
&lt;/pre&gt;&lt;p&gt;In addition to extending our new collection, we&amp;#8217;ll make another change so that instead of setting the URL property, we now set the sailsCollection property. And that&amp;apos;s all there is to it. Open up the application into two different browsers (e.g. Chrome and Safari) and signup two separate users. You should see that posted messages from either of the browsers get immediately shown on the other, no polling, no trouble.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/05/Sails_Chat.png" alt="Chat Screenshot" /&gt;&lt;/figure&gt;&lt;hr
/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Sails is a breath of fresh air, within a clutter of frameworks. It checks its ego at the door, and does what it can to help the developer instead of the brand. I have been chatting with the Sails devs and I can tell you that there&amp;#8217;s even more awesomeness in the works, and it will be interesting to see where this framework goes.&lt;/p&gt;&lt;p&gt;So in conclusion, you&amp;#8217;ve learned how to setup, use, and secure your data from within Sails, as well as how to interface it with the popular Backbone library.&lt;/p&gt;&lt;p&gt;Like always, if you have any comments, feel free to leave them below, or join us on the Nettuts+ IRC channel (&amp;quot;#nettuts&amp;quot; on freenode). Thank you for reading.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=usUcBrdA3Cs:bVMZM5XcVQQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=usUcBrdA3Cs:bVMZM5XcVQQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=usUcBrdA3Cs:bVMZM5XcVQQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=usUcBrdA3Cs:bVMZM5XcVQQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=usUcBrdA3Cs:bVMZM5XcVQQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=usUcBrdA3Cs:bVMZM5XcVQQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=usUcBrdA3Cs:bVMZM5XcVQQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=usUcBrdA3Cs:bVMZM5XcVQQ:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/usUcBrdA3Cs" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/javascript-ajax/working-with-data-in-sails-js/feed/</wfw:commentRss> <slash:comments>13</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/javascript-ajax/working-with-data-in-sails-js/</feedburner:origLink></item> <item><title>What Are You Using?</title><link>http://feedproxy.google.com/~r/nettuts/~3/tkWqdSAi6dQ/</link> <comments>http://net.tutsplus.com/articles/what-are-you-using/#comments</comments> <pubDate>Mon, 10 Jun 2013 22:30:10 +0000</pubDate> <dc:creator>Rey Bango</dc:creator> <category><![CDATA[Articles]]></category> <category><![CDATA[General]]></category> <category><![CDATA[what are you using?]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32373</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32373&amp;c=163147886' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32373&amp;c=163147886' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;We spend a lot of time following the thought leaders in web development, in many cases using the tools and libraries they&amp;#8217;ve built, reading the posts they&amp;#8217;ve written, articulating cool techniques they&amp;#8217;ve learned, and in some cases, attending the defining conference for a specific language. But wouldn&amp;#8217;t it be great to learn what they focus on and what they use to build such awesomeness?&lt;/p&gt;&lt;p&gt;&lt;span
id="more-32373"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I reached out to a group of some of the best and brightest developers in web development to answer those very questions. These are developers that have made strong contributions to the web development community, are highly regarded by their peers for their technical abilities, and continue to help push web development forward via content, code, and leadership. You can check out their bios, below, for more details about them.&lt;/p&gt;&lt;p&gt;These folks are incredibly busy, so I narrowed my questions down to four simple ones:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;What&amp;#8217;s your primary development focus?&lt;/li&gt;&lt;li&gt;What hardware are you using for development?&lt;/li&gt;&lt;li&gt;Which editor or IDE do you use?&lt;/li&gt;&lt;li&gt;What software can you not live without on a daily basis?&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Below, you&amp;#8217;ll find the answers they gave and hopefully discover some tools that could make your development much easier. You&amp;#8217;ll definitely find common themes (Sublime) and a few nuggets that are new, at least to me.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Scott Gonzalez&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/scott-gonzalez.png" alt="scott-gonzalez" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; I&amp;#39;m a full-stack web application developer, with a focus on JavaScript. I&amp;#39;ve been contributing to jQuery since 2007 and I&amp;#8217;m currently the &lt;a
href="http://jqueryui.com/about/"&gt;Project Lead for jQuery UI&lt;/a&gt;. I&amp;#39;m active in the Node.js, WHATWG, and W3C communities as well.&lt;/p&gt;&lt;p&gt;Connect with Scott on his &lt;a
href="http://scottgonzalez.com/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/scott_gonzalez"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Web development, mostly client-side JS and Node.js.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;MacBook Pro.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Sublime Text with &lt;a
href="https://github.com/SublimeText/TrailingSpaces"&gt;TrailingSpaces&lt;/a&gt;, Pretty JSON, GitGutter, and &lt;a
href="https://github.com/revolunet/sublimetext-markdown-preview"&gt;Markdown Preview&lt;/a&gt;.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Git, GitHub, Apache, Chrome, &lt;a
href="http://www.conceitedsoftware.com/linkinus"&gt;Linkinus&lt;/a&gt;, Skype, Node.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Raymond Camden&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/raymond-camden.jpg" alt="raymond-camden" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Raymond is a senior developer evangelist for Adobe. His work focuses on web standards, mobile development, and ColdFusion. He&amp;#39;s a published author and presents at conferences and user groups on a variety of topics.&lt;/p&gt;&lt;p&gt;Connect with Raymond on his &lt;a
href="http://www.raymondcamden.com/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/cfjedimaster"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My primary development focus, in general, is on web standards, &lt;a
href="http://www.adobe.com/products/creativecloud.html"&gt;Creative Cloud&lt;/a&gt; (with a focus on the HTML tools), and typically the &amp;quot;non-sexy&amp;quot; part of client-side dev. I can appreciate CSS, but I get more excited by things like storage, JavaScript, and forms.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My hardware is a MacBook Pro. I do a lot of mobile development though, so I test with an iPhone, an Android phone, and various tablets. Oddly, the only Microsoft hardware I use daily is my keyboard. I&amp;#39;ve been using &amp;quot;Natural&amp;quot; keyboards for almost 15 years. I&amp;#39;m addicted to them.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My editor is &lt;a
href="http://brackets.io/"&gt;Brackets&lt;/a&gt;, an open source editor we launched about a year or so ago. It&amp;#39;s got great ties to Chrome and a cool extensibility layer.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Based on what I see in my OS X dock right now, the tools I use every day are my browser, my editor, Tweetdeck, and Evernote. (I keep everything in Evernote, from project stuff, to random tips.)&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;John-David Dalton&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/john-david-dalton.jpg" alt="john-david-dalton" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; JDD is the co-maintainer of &lt;a
href="http://jsperf.com/"&gt;jsPerf&lt;/a&gt;/&lt;a
href="http://benchmarkjs.com/"&gt;Benchmark.js&lt;/a&gt;, an ES5 compliance evangelist, a JavaScript library enthusiast, a two time Microsoft MVP recipient for IE testing, and a Chakra performance program manager at Microsoft.&lt;/p&gt;&lt;p&gt;Connect with JDD on &lt;a
href="https://github.com/jdalton"&gt;Github&lt;/a&gt; and &lt;a
href="https://twitter.com/jdalton"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Low level utility libs and benchmarking. I&amp;#39;m a libs fan, and dev&amp;#8217;ing around them. JS development isn&amp;#8217;t my day job at Microsoft, so no client work or anything like that.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My day job dev&amp;#8217;ing is done on Windows 8 and IE10. My personal dev machine is a 13&amp;#8243; MacBook Pro running OS X 10.7.5, with a 2.3GHz processor and 8GBs of RAM.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I use &lt;a
href="http://www.activestate.com/komodo-edit"&gt;Komodo Edit&lt;/a&gt; on OS X and Windows. I love its advanced search. I search by regexp and nested files all the time.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;I use just about every browser..&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Besides my text editor, I use total finder for OS X (this makes its windows manageable). I also have just about every browser; 22 different Chrome versions, five versions of IE, 23 versions of Firefox, 12 versions of Opera, and six versions of Safari. Before I release a version bump, I ensure the given project runs in the environments/browsers that I state it should run in, which is &lt;em&gt;why&lt;/em&gt; I have all the browsers.  I also have Node, &lt;a
href="http://ringojs.org/"&gt;Ringo&lt;/a&gt;, &lt;a
href="https://developer.mozilla.org/en-US/docs/Rhino"&gt;Rhino&lt;/a&gt;, and &lt;a
href="https://github.com/tlrobinson/narwhal"&gt;Narwhal&lt;/a&gt;.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Stephanie Sullivan Rewis&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/stephanie-rewis.jpg" alt="stephanie-rewis" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Stephanie is Director, Web Strategy and Marketing Technologies at Contatta. As a front-end developer, she&amp;#8217;s presented sessions at conferences worldwide, including &lt;a
href="http://www.howdesignlive.com/"&gt;HOW Design&lt;/a&gt;, &lt;a
href="http://www.uie.com/brainsparks/topics/events/ui16/"&gt;UI16&lt;/a&gt;, An Event Apart, Microsoft&amp;#8217;s MIX, Macworld, SXSW, Adobe Max, and numerous others. She&amp;#8217;s a published author, and while principal at W3Conversions, worked with a wide variety of organizations from Newsweek, MLB, New York Magazine, Adobe, and SalesForce.com to Disney&amp;#8217;s &amp;#8220;TRON&amp;#8221; movie site.&lt;/p&gt;&lt;p&gt;Connect with Stephanie on her &lt;a
href="http://blog.w3conversions.com/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/stefsull"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I&amp;#39;m a front-end dev, but I&amp;#39;m wearing a few extra hats due to being in startup mode at Contatta. That means I have the &lt;em&gt;honor&lt;/em&gt; of choosing and implementing our new corporate CMS—so I&amp;#39;m digging into PHP a bit, in addition to my usual development.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I don&amp;#39;t use any special hardware. I work on a 17&amp;quot; MacBook Pro (that I haven&amp;#39;t upgraded because I don&amp;#39;t want to downsize to a 15&amp;quot;). If I&amp;#39;m at my desk, I&amp;#39;m also plugged into a second monitor. I choose to buy my monitors somewhere like Costco, rather than using the high-end models, so that I can view my site like &amp;quot;an average user&amp;quot; does.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Currently, I&amp;#39;m using Sublime Text 2 for daily development. However, if Adobe&amp;#39;s open source code editor, Brackets, keeps going in the direction they showed at MAX, I&amp;#39;ll probably give it a whirl at some point. I also use Dreamweaver to build my email campaigns in.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;I give Chrome a daily workout, sometimes with over 150 tabs.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Outside of my editors, I always have &lt;a
href="http://incident57.com/codekit/"&gt;CodeKit&lt;/a&gt; to compile my Sass and minify my CSS and JS. I use Git for Source control and push my code to the repository via &lt;a
href="http://www.git-tower.com/"&gt;Tower&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I use &lt;a
href="https://www.hipchat.com"&gt;HipChat&lt;/a&gt; to communicate with the rest of the company throughout the day. But the best thing about HipChat is Hu Bot, which handles the deployment from my Git repository to either staging or production. I adore my bot!&lt;/p&gt;&lt;p&gt;My designer uses Fireworks, so I sometimes have that open, slicing and dicing. (Yea, I know Adobe isn&amp;#39;t updating it, but it does what he needs, so we&amp;#39;ll have to pry it from his cold, dead fingers someday.) I always have Spotify open—usually playing an Artist Radio I make based on my mood or the kind of dev I&amp;#39;m doing (today, it&amp;#39;s a Hellsongs station).&lt;/p&gt;&lt;p&gt;Finally, I give Chrome a daily work out, sometimes with over 150 tabs (yes, I have a problem). I use it both for the Inspector and the plugins that I can&amp;#39;t live without (&lt;a
href="https://agilebits.com/onepassword"&gt;1Password&lt;/a&gt;, OneTab, ColorZilla, &lt;a
href="https://chrome.google.com/webstore/detail/cache-killer/jpfbieopdmepaolggioebjmedmclkbap?hl=en"&gt;Cache Killer&lt;/a&gt;, and &lt;a
href="https://www.dragdis.com/"&gt;Dragdis&lt;/a&gt;, to name a few) as well as to house tabs of all the other things I have to keep track of, like Google Analytics, MailChimp, &lt;a
href="http://sproutsocial.com/"&gt;SproutSocial&lt;/a&gt;, Google Docs, and anything else I&amp;#39;m currently researching.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Christian Heilmann&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/christian-heilman.jpg" alt="christian-heilmann" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Chris Heilmann has dedicated a lot of his time to making the web better. Originally coming from a radio journalism background, he built his first web site from scratch around 1997 and spent the following years working on lots of large, international web sites. He then spent a few years in Yahoo building products, explaining and training people, and is now at Mozilla. Chris wrote and contributed to four books on web development and wrote many articles and hundreds of blog posts for Ajaxian, Smashing Magazine, Yahoo, Mozilla, ScriptJunkie, and many more.&lt;/p&gt;&lt;p&gt;Connect with Christian on his &lt;a
href="http://christianheilmann.com"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/codepo8"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My primary focus is making sure that the next person taking over after me, gets code that is easy to understand and simple to extend. Sadly enough, this is going out of fashion and a lot of focus is placed on &amp;quot;getting it out the door&amp;quot;. I really think that we learn the most from each other&amp;#39;s work and where better to write clean and understandable code than in our deliveries?&lt;/p&gt;&lt;p&gt;My focus is the web, not just one browser or one closed environment. This means you need to be very flexible in your code. Being very flexible can mean making it work right here, right now, or spending time on making it easily extendable, for new features that may be added in the future. I think after 16 years of web development, we should be at a stage where we stop hacking things together and replacing them continuously.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;MacBook Air, I am always on the go and have little space or time to set up large hardware components.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Sublime Text 2, it&amp;#8217;s incredible.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Browsers and their developer tools, the command line for Git, an IRC client, Dropbox and Spotify. I have found more and more, that I&amp;#8217;ve become independent of fat client software and I use a lot of online services instead.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Ryan Grove&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/ryan-grove.jpg" alt="ryan-grove" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Ryan Grove is a Sorcerer at &lt;a
href="http://www.smugmug.com/"&gt;SmugMug&lt;/a&gt;, a &lt;a
href="http://yuilibrary.com/"&gt;YUI&lt;/a&gt; reviewer, and was once an underage model for a Japanese clothing catalog. He likes pie, movies, pie, old style sailing ships, and pie.&lt;/p&gt;&lt;p&gt;Connect with Ryan on his &lt;a
href="http://wonko.com/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/yaypie"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I spend most of my time these days building client-side JS components and features for SmugMug. In my free time I write lots of Node.js code and occasionally some Ruby (although JS has really taken over my focus in the last few years). At SmugMug, our framework of choice is YUI 3, and I&amp;#39;m also a core reviewer for YUI, so I contribute a lot of code to it and also review changes from other committers and contributors.&lt;/p&gt;&lt;p&gt;On a typical day, I might write some non-public SmugMug code, some open source SmugMug code, and some open source YUI code. We try to open source as much of our JS as possible, and a lot of that goes back into YUI these days.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;When I&amp;#8217;m traveling I use a 13&amp;#8243; Macbook Air.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I work from home on a 2.8GHz Quad-Core Mac Pro with 16GB of RAM, an SSD, and two 30&amp;#8243; HP ZR30w monitors that are fantastic for viewing big gorgeous photos and videos. When I&amp;#39;m traveling I use a 13&amp;#8243; MacBook Air (mid-2011, Core i7), which I love to death. Although, the screen isn&amp;#39;t &lt;em&gt;quite&lt;/em&gt; as good as my desktop setup for viewing big gorgeous photos.&lt;/p&gt;&lt;p&gt;I also have a ridiculous collection of mobile devices that I use for testing. At least one of every model of iPhone and iPad, several Android devices, a Windows phone, and a Chromebook.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I use &lt;a
href="http://www.sublimetext.com/3"&gt;Sublime Text 3&lt;/a&gt; for everything. I want to marry it and have its kittens.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;In addition to Sublime Text, my must-have apps include &lt;a
href="http://www.jshint.com/"&gt;JSHint&lt;/a&gt; (for keeping me honest), iTerm 2, &lt;a
href="http://adium.im/"&gt;Adium&lt;/a&gt; (for IRC), OS X Messages (for iMessage and Jabber), Tower (a GUI Git client), Dropbox and Rsync (for syncing source and data across various machines), &lt;a
href="http://www.haystacksoftware.com/arq/"&gt;Arq&lt;/a&gt; (for backup), Gmail, GitHub, and of course Google Chrome as my browser of choice.&lt;/p&gt;&lt;p&gt;SmugMug has lots of remote workers, so we use Google Hangouts for meetings and quick face-to-face chats. Additionally, IRC is an important communication medium for us. SmugMug has its own IRC server with a &lt;a
href="http://wiki.znc.in/ZNC"&gt;znc bouncer&lt;/a&gt;, and I use the &lt;a
href="http://colloquy.mobi/"&gt;Colloquy iOS app&lt;/a&gt; to get push notifications if someone mentions my name or sends me a message while I&amp;#39;m not at my desk.&lt;/p&gt;&lt;p&gt;&lt;a
href="http://www.charlesproxy.com/"&gt;Charles&lt;/a&gt;, cURL, and the &lt;a
href="https://chrome.google.com/webstore/detail/rest-console/cokgbflfommojglbmbpenpphppikmonn?hl=en"&gt;REST Console Chrome extension&lt;/a&gt; are indispensable for debugging HTTP requests and working with APIs. Oh, and I&amp;#39;ve gotten so used to using &lt;a
href="http://www.alfredapp.com/"&gt;Alfred&lt;/a&gt; (an app launcher and search tool) that I can&amp;#39;t function when I use a machine that doesn&amp;#39;t have it installed. I hit Control+Space and type &amp;quot;&lt;code&gt;mdn [something or other]&lt;/code&gt;&amp;quot; about a thousand times a day to look up docs, among many other things.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Cody Lindley&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/cody-lindley.jpg" alt="cody-lindley" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Front-end/UI/JS engineer and author. Lover of Christ, people, logic, and the dying art of debate, conversation, and rational thinking. Husband and father of three boys.&lt;/p&gt;&lt;p&gt;Connect with Cody on his &lt;a
href="http://codylindley.com/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/codylindley"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My focus is on front-end code (i.e. HTML, CSS, and JavaScript) used to build thick client web applications and websites for desktop users. I cross over into tablet and mobile web development when necessary.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My setup for years now has been a MacBook Pro, 27&amp;#8243; Apple Display, Apple Magic Mouse, and an Apple wireless keyboard.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I use the Sublime Text 2 editor.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;That would be &lt;a
href="http://www.syntevo.com/smartgithg/index.html"&gt;SmartGit&lt;/a&gt;, Sublime Text, &lt;a
href="http://mizage.com/divvy/"&gt;Divvy&lt;/a&gt;, &lt;a
href="http://jumpcut.sourceforge.net/"&gt;JumpCut&lt;/a&gt;, Google (search, gmail, drive, calendar), Skype, Terminal, Chrome, Tweetdeck, Parallels, Textual, Dropbox, Github, &lt;a
href="https://www.assembla.com/"&gt;Assembla&lt;/a&gt;.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Luke Smith&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/luke-smith.png" alt="luke-smith" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Locally sourced, (indirectly) grass fed, all organic web developer out of Portland, Oregon. I&amp;#39;m fortunate to work with the amazing and inspiring team at SmugMug. Speaking of amazing and inspiring teams, previously I was a YUI core developer for five years, and am still contributing to the project today. Did I say team? I meant community. Seriously, you all are awesome.&lt;/p&gt;&lt;p&gt;Connect with Luke on &lt;a
href="https://twitter.com/ls_n"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;More than anything, really, I like helping people out when I can.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I&amp;#39;m pretty much all JavaScript, all day every day. Specifically, I prefer to work on lower level API stuff, writing abstractions and tools to build other stuff on top of, such as event systems, promises, and XHR/data IO frameworks. I try very hard to make APIs that are intuitive, flexible, and fast. Principle of, least surprise-friendly stuff. But at the same time, I like solving little UI implementation challenges with higher level components. More than anything, really, I like helping people out when I can. I want to contribute more to JS, DOM spec, and standards work.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;13&amp;quot; MacBook Air (one for work, one for personal), 2GHz Core i7 with 8GBs of RAM and a 500GB SSD (personal is 4GB/256GB). My work machine is hooked up to a 22&amp;quot; POS display that I bought years ago for extra real estate, an Apple keyboard, and a magic track pad. I hate the non-split keyboard layout, but love the key shape and action more, so I deal with it. I also hate the use of the word &amp;quot;magic&amp;quot; in the trackpad&amp;#39;s name.&lt;/p&gt;&lt;p&gt;As to the Air, I&amp;#39;ve gone through a number of laptops and desktop units and until the Air, I never had any affection (good or bad) for the tech. The Air is awesome. It&amp;#39;s the best laptop I&amp;#39;ve ever had, the best computer I&amp;#39;ve ever had. I genuinely love the thing. Fortunately, I haven&amp;#39;t pushed its processing limits (yet) to the extent where beefier hardware is necessary. And I suppose I should mention the Yapster headset, since I work remotely. It&amp;#39;s good enough for the money vs. how much I use it.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;&lt;a
href="http://www.vim.org/"&gt;Vim&lt;/a&gt; FTW. That is all.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I live in Terminal, Vim, Git, and Chrome (dev tools \m/). Supporting staff are &lt;a
href="https://github.com/yui/shifter"&gt;Shifter&lt;/a&gt; (for YUI stuff), Github&amp;#39;s pull request and issues systems, VirtualBox, and 1Password. The distractionary cast and crew are: Mail.app (for lack of a better client), &lt;a
href="https://www.macupdate.com/app/mac/33399/itsy"&gt;Itsy&lt;/a&gt; (minimalist twitter client), &lt;a
href="http://reederapp.com/"&gt;Reeder&lt;/a&gt;, iOS Reminders app, and Adium. I&amp;#39;m sure I&amp;#39;m missing several that I take for granted.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Chris Williams&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/chris-williams.jpg" alt="chris-williams" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Chris is the VP of Product Engineering at &lt;a
href="http://www.saferaging.com/"&gt;SaferAging&lt;/a&gt; and the organizer of &lt;a
href="http://jsconf.com/"&gt;JSConf US&lt;/a&gt; and &lt;a
href="http://robotsconf.com/"&gt;RobotsConf&lt;/a&gt;. He is the author of the &lt;a
href="https://github.com/voodootikigod/node-serialport"&gt;node-serialport&lt;/a&gt;, originator of the &lt;a
href="https://github.com/voodootikigod/logo.js"&gt;JS Community Logo&lt;/a&gt;, and assists in the creation of amazing tech events like &lt;a
href="http://nodebots.io/"&gt;NodeBots&lt;/a&gt; and &lt;a
href="http://www.nodecopter.com/"&gt;NodeCopter&lt;/a&gt;, among others. He is constantly inspired by his wife and two amazing children.&lt;/p&gt;&lt;p&gt;Connect with Chris on &lt;a
href="http://jsconf.com/"&gt;JSconf&lt;/a&gt; and &lt;a
href="http://robotsconf.com/"&gt;RobotsConf&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My focus actually spreads across the entire bow of development these days, from programming and developing hardware sensors, to high availability server infrastructure and development, to frontend information presentation. In a given week, I will be soldering hardware, writing squirrel firmware, monitoring and upgrading servers, and developing new user interfaces and interactions (not necessarily web or visual based). To pick a single &amp;quot;primary&amp;quot; focus is tough because they are all supportive and necessary for creating the products I am working towards or supporting.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I mainly use Apple products (2010 MacBook Air when on the road, 2008 Mac Pro when at work, 2012 Mac Mini at home) due to their incredible construction quality and visual appeal. I split my time almost down the middle between raw terminal (Fish Shell yay!) use and GUI interface applications, so the fluidity between the two afforded by Mac OS X nicely supports my standard workflow.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;I&amp;#8217;ll opt for different editors based on the contextual environment I&amp;#8217;m working in.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I&amp;#8217;ll opt for different editors based on the contextual environment I&amp;#8217;m working in. On servers, I&amp;#8217;ll use VIM simply because it&amp;#8217;s everywhere. On my local machine, I have opted for Sublime Text 3 at this point, though I am always dabbling with others, mainly out of curiosity rather than need.&lt;/p&gt;&lt;p&gt;I use a simple set of plugins (&lt;a
href="https://github.com/falsefalse/sublime-ejs"&gt;EJS&lt;/a&gt;, &lt;a
href="https://github.com/sergeche/emmet-sublime"&gt;Emmet&lt;/a&gt;, Go, &lt;a
href="https://github.com/jisaacks/GitGutter"&gt;GitGutter&lt;/a&gt;, JSFormat, Squirrel) that basically provide syntax highlighting and formatting for me. I find standard IDEs to be too cumbersome and heavy. I get lost in all it provides to be honest. Even with Sublime, I often get lost in the key combos as I just want to get done, what I need to get done, no fluff, no pomp, just optimize on time to complete the task.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Sublime Text 3 (as mentioned above), but really that boils down to a raw text editor more than anything. &lt;a
href="http://www.iterm2.com/"&gt;iTerm2&lt;/a&gt; and &lt;a
href="http://fishshell.com/"&gt;Fish shell&lt;/a&gt; have saved my life on a near daily basis. &lt;a
href="https://www.wunderlist.com/"&gt;Wunderlist&lt;/a&gt; is something I basically cannot live without because I am just juggling too much stuff in my head at any given point. Outside of software, I couldn&amp;#39;t live without my &lt;a
href="http://www.daskeyboard.com/"&gt;Das Keyboard&lt;/a&gt; &amp;#8212; typing on anything else these days feels unnatural and discomforting.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Aaron Newton&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/aaron-newton.jpg" alt="aaron-newton" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Aaron Newton is a jack of all trades and, arguably, king of none. A veteran of numerous startups, most recently &lt;a
href="http://www.cloudera.com/"&gt;Cloudera&lt;/a&gt;, he is now Head of Product at Thanx, a mobile loyalty application. As a contributor to the &lt;a
href="http://mootools.net"&gt;MooTools&lt;/a&gt; framework from its first release, he has authored numerous tutorials, a book, and more code than he can ever hope to maintain, most of it being JavaScript.&lt;/p&gt;&lt;p&gt;Connect with Aaron on &lt;a
href="http://mootools.net"&gt;MooTools&lt;/a&gt; and &lt;a
href="https://twitter.com/anutron"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;These days I&amp;#39;m a product manager at Thanx. I&amp;#39;m very technical, so I have a lot of discussions about specific implementations while still doing code reviews and chipping in on development when I can. Our product is primarily a mobile application with a native iOS implementation and an HTML5 version for mobile browsers. We have an Android app which is basically a browser that uses this HTML5 implementation. I tend to contribute on the HTML5 implementation and also to our more traditional web appliations &amp;#8211; a dashboard for our customers and internal tools for our own use.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;My trusty MacBook Pro. Everything else runs on AWS / Heroku.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Lately Sublime. I was pretty hardcore about TextMate for years, but finally got tired of not having any updates. I like all the community support for Sublime (and that it can run TextMate plugins), but the two features that finally, really made me switch were the split views and, more than anything, the lightning fast search. Searching on TextMate is the new &amp;quot;my code is compiling so I&amp;#39;m going to go get a coffee.&amp;quot;&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;div&gt;Aside from obvious stuff like web browsers (I use Chrome primarily, but I have &lt;a
href="http://fluidapp.com/"&gt;Fluid&lt;/a&gt; apps for Gmail and &lt;a
href="http://www.atlassian.com/software/jira/"&gt;JIRA&lt;/a&gt;, etc), other tools that come to mind are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a
href="http://getcloudapp.com/"&gt;Cloudapp&lt;/a&gt; &amp;#8211; I share files with this all the time. I pay for the pro model and don&amp;#39;t give it a second thought when I want to send a screenshot or something somewhere.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://www.techsmith.com/jing.html"&gt;Jing&lt;/a&gt; &amp;#8211; most of the time I use the built in screenshot functionality in OSX, but sometimes I want to capture video or annotate the screenshot and that&amp;#8217;s when Jing comes in handy.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://www.sequelpro.com/"&gt;Sequel Pro&lt;/a&gt; &amp;#8211; aside from being a great, free SQL tool for Mac, I&amp;#39;m in love with the &lt;a
href="http://cl.ly/1X3J453Q2U0g"&gt;app icon&lt;/a&gt;, which is perhaps the best icon for any app, I&amp;#39;ve ever seen.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://jumpcut.sourceforge.net/"&gt;Jumpcut&lt;/a&gt; &amp;#8211; this little clipboard saver has removed that nagging sensation that I used to have whenever I hit &amp;quot;copy&amp;quot;, that feeling that there&amp;#39;s something on your clipboard that you need to put somewhere before you replace the buffer.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://totalterminal.binaryage.com/"&gt;Total Terminal&lt;/a&gt; &amp;#8211; I switch to my terminal all the time. Visor locks it to the top of the screen (think of the console in Quake) so it&amp;#39;s always only one keystroke away. See also: Total Finder, from the same publisher, which adds chrome-style tabs to Finder (and a bunch of other features).&lt;/li&gt;&lt;li&gt;&lt;a
href="http://gitx.org/"&gt;GitX&lt;/a&gt; &amp;#8211; I use the command line for nearly everything git related&amp;#8230; except for staging commits. I still use the command line if I&amp;#39;m staging EVERYTHING, but with GitX it&amp;#39;s super easy to take several changes and break it up into small commits, even at the file level.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Ben Cherry&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/ben-cherry.jpg" alt="ben-cherry" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Ben lives in San Francisco, where he is an Engineer at Pushd, focusing on Ruby and iOS. Previously he built a failed startup on iOS and Node.js, and before that he wrote JavaScript at Twitter and Slide. He maintains a programming blog, mostly about JavaScript, at &lt;a
href="http://www.adequatelygood.com"&gt;http://www.adequatelygood.com&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Connect with Ben on his &lt;a
href="http://www.adequatelygood.com"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/bcherry"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I spent three years doing heavy JavaScript for Slide and Twitter, but more recently I&amp;#39;m working on iOS and Ruby, while only occasionally working with JavaScript.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;A 13&amp;quot; Retina MacBook Pro with a 27&amp;quot; Thunderbolt display.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;SublimeText 2. I Love it.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;That would be SublimeText 2, iTerm 2, Google Chrome, 1Password, Gmail, &lt;a
href="http://flipboard.com/"&gt;Flipboard&lt;/a&gt;, Twitter, Facebook, Reddit.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Jacob Thornton&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/jacob-thornton.jpeg" alt="jacob-thornton" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; I write code &lt;a
href="https://medium.com/"&gt;@medium&lt;/a&gt; and I&amp;#39;ve opensourced a few things (like &lt;a
href="http://twitter.github.io/bootstrap/"&gt;Bootstrap&lt;/a&gt; and &lt;a
href="https://github.com/bower/bower"&gt;Bower&lt;/a&gt;). I used to give talks and occasionally, I write about the web.&lt;/p&gt;&lt;p&gt;Connect with Jacob on his &lt;a
href="http://byfat.xxx/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/fat"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I suppose I spend most of my time on general front-end (JS/CSS/HTML) development, though I do a good amount of tool/build development and a fair amount of simple server work. I&amp;#39;ve also been trying to up my accessibility chops – meeting a lot of really rad/super helpful people in this space (like &lt;a
href="https://twitter.com/vick08"&gt;Victor Tsaran&lt;/a&gt; from Paypal and &lt;a
href="http://nyti.ms/XxuOqm"&gt;Joshua Miele&lt;/a&gt;).&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I use a 15&amp;quot; Retina MacBook Pro at work and a 13&amp;quot; MacBook Air at home. I do a &lt;em&gt;ton&lt;/em&gt; of testing on different devices though: iPads, iPhones, Android tablets/phones, Blackberry, and even Windows slate.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;I use Sublime Text 2.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I use Sublime Text 2. I used Vim (poorly) for a while, but I found most other front-end developers didn&amp;#39;t really use it either, and it was weird mentally, always switching back and forth for me. So, I just point and click like a noob now. Honestly, I&amp;#8217;m terrible with computers. I know a lot of engineers who are so dope with their computers, and make all of this custom stuff happen, but I literally have no idea what I&amp;#8217;m doing most of the time.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;&lt;a
href="http://www.rdio.com/"&gt;Rdio&lt;/a&gt; &amp;#8211; I am useless without music.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Lea Verou&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/lea-verou.jpg" alt="lea-verou" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Lea works as a Developer Advocate for &lt;a
href="http://w3.org/"&gt;W3C&lt;/a&gt;. She has a long-standing passion for open web standards, which she fulfills by researching new ways to use them, &lt;a
href="http://lea.verou.me"&gt;blogging&lt;/a&gt;, &lt;a
href="http://lea.verou.me/speaking"&gt;speaking&lt;/a&gt;, &lt;a
href="http://lea.verou.me/publications"&gt;writing&lt;/a&gt;, and coding popular open source &lt;a
href="http://lea.verou.me/projects/"&gt;projects&lt;/a&gt; to help fellow developers. She&amp;#8217;s also a member of the CSS Working Group, which architects the language itself.&lt;/p&gt;&lt;p&gt;Connect with Lea on her &lt;a
href="http://lea.verou.me/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/leaverou"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Anything about the client-side: I do HTML, CSS, JavaScript, or even design and UX! However, I have a penchant for CSS, which became even stronger after I joined the &lt;a
href="http://www.w3.org/Style/CSS/members.en.php3"&gt;CSS Working Group&lt;/a&gt;.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;A 13&amp;#8243; MacBook Air Ultimate that I bought last June. I love it. Its touchpad had some issues for the past few months, but I recently got it replaced so I fell in love with my lil&amp;#8217; MacBaby (yes, I have a pet name for it, is there a problem? :) all over again. &lt;3&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;&lt;a
href="http://macrabbit.com/espresso/"&gt;Espresso&lt;/a&gt;. I know there are better text editors around, but its FTP integration is addictively good.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Native apps: Espresso, Transmit, &lt;a
href="http://incident57.com/codekit/"&gt;CodeKit&lt;/a&gt;, Adobe Illustrator, Chrome, Safari, Firefox, Opera, &lt;a
href="http://nightly.webkit.org/"&gt;WebKit nightlies&lt;/a&gt;, Chrome Canary.&lt;/p&gt;&lt;p&gt;Web apps: Browserstack, &lt;a
href="http://dabblet.com/"&gt;Dabblet&lt;/a&gt;, &lt;a
href="http://copypastecharacter.com/"&gt;copypastecharacter.com&lt;/a&gt;, &lt;a
href="http://css.coloratum.com/"&gt;css.coloratum.com&lt;/a&gt;, &lt;a
href="https://workflowy.com/"&gt;Workflowy&lt;/a&gt;, and Github.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Jonathan Snook&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/jonathan-snook.png" alt="jonathan-snook" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Jonathan Snook is a Web Designer/Developer who works at &lt;a
href="http://www.shopify.com/"&gt;Shopify&lt;/a&gt;. He can speak, he can write, he can develop websites with all his might.&lt;/p&gt;&lt;p&gt;Connect with Jonathan on his &lt;a
href="http://snook.ca/"&gt;Blog&lt;/a&gt; and &lt;a
href="https://twitter.com/snookca"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;These days, I mostly focus on front-end development. HTML, CSS and JavaScript fill up my time.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I have an 11&amp;#8243; MacBook Air that is my primary machine. When it comes to testing, though, I prefer testing on an actual device as much as I can. I have a Samsung tablet with Windows 8, a Nexus 7, an iPad Mini, an iPhone, and even an older phone with WebOS. Okay, I might not use that last one very much. No BlackBerry device yet. For IE6 through IE9 testing, I use VMWare with &lt;a
href="http://www.modern.ie/en-us/virtualization-tools"&gt;Windows XP, Windows 7 and Windows 8 VMs&lt;/a&gt;, too.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Vim. It&amp;#8217;s so handy and I like having something familiar to use when I&amp;#8217;m logged into a remote Linux box.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Vim, of course, and my browser of choice these days: Chrome. I&amp;#8217;ve been using Google Docs more and more, which has replaced Microsoft Office. Google has really been doing a good job at improving their toolset. I&amp;#8217;m starting to buy into the whole Google ecosystem.&lt;/p&gt;&lt;div
class="webroundup"&gt;&lt;hr
/&gt;&lt;h2&gt;Peter Wagenet&lt;/h2&gt;&lt;div&gt; &lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/peter-wagenet.jpg" alt="peter-wagenet" width="150" class="alignnone size-full wp-image-32387" /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Peter has been developing web applications for nearly fifteen years. He is currently an &lt;a
href="http://emberjs.com/"&gt;Ember&lt;/a&gt; Core Team member, previously serving on the &lt;a
href="http://sproutcore.com/"&gt;SproutCore&lt;/a&gt; team. He also has extensive experience with Ruby on Rails and has dabbled in iOS development. These days you can find him working for Tilde on awesome projects like &lt;a
href="http://skylight.io"&gt;Skylight&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Connect with Peter on &lt;a
href="https://twitter.com/wagenet"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What&amp;#8217;s your primary development focus?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I spend most of my time doing Ember development with a bit of Rails thrown in. Right now, I&amp;#8217;m consulting two days a week on Ember and the rest is spent working on Tilde projects, mainly &lt;a
href="http://skylight.io"&gt;Skylight&lt;/a&gt;, which is an Ember client with a Rails backend. It also has a Java component, though I don&amp;#8217;t work on that.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What hardware are you using for development?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;I use a 2012 MacBook Air with a 2GHz Core i7 and 8GBs of RAM. I also have a 27&amp;#8243; Cinema Display. I used to have a 20&amp;#8243; LCD hooked up as well with a USB to DVI adapter, but decided to make my desk a little less crowded.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; Which editor or IDE do you use?&lt;/h4&gt;&lt;/div&gt;&lt;p&gt;Recently I&amp;#8217;ve been using Sublime Text 3. When I first started, I used TextMate, which I loved. However, I got tired of waiting for TextMate 2 and ended up switching to VIM. I fell in love with the VIM keybindings, but was still frustrated by the plugin experience and wished I could have something a bit more polished. For me, Sublime&amp;#8217;s Vintage mode gets 95% of what I did with VIM&amp;#8217;s keybindings, it has a better plugin architecture, and it&amp;#8217;s more polished. I&amp;#8217;ve never felt a big pull towards using a full-blown IDE, autocomplete is good enough for me. The only full-blown IDE I&amp;#8217;ve used is Xcode and I find that I&amp;#8217;m always missing keybindings when I use it.&lt;/p&gt;&lt;hr
/&gt;&lt;div
class="question"&gt;&lt;h4&gt;&lt;span&gt;Q&lt;/span&gt; What software can you not live without on a daily basis?&lt;/h4&gt;&lt;/div&gt;&lt;blockquote
class="pullquote"&gt;&lt;p&gt;I browse in Chrome.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I browse in Chrome, though I&amp;#8217;ve heard some cool things are in works for the Firefox dev tools, so I might be convinced to change. For chat and communication, I use Adium for AIM, GTalk, IRC and Flint for Campfire. I still use plain old Mail.app and the basic Twitter app as well. I&amp;#8217;m not a huge power tools sort of guy, but I&amp;#8217;ve been enjoying Divvy a lot recently for positioning windows. 1Password is also indispensable. Since I have a lot of menu bar items, I&amp;#8217;ve also found &lt;a
href="http://www.macbartender.com/"&gt;Bartender&lt;/a&gt; to be super useful.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;In Closing&lt;/h2&gt;&lt;p&gt;So, there you go. You now have a nice reference to what many of the leaders in web development are using day in, and day out. We&amp;#8217;d like to send out a big &amp;#8220;Thank You&amp;#8221; to all of the developers who participated!&lt;/p&gt;&lt;p&gt;Feel free to share the tools, hardware, editor/IDE, and software that you use everyday, in the comments.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=tkWqdSAi6dQ:iHhkDHNUSQk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=tkWqdSAi6dQ:iHhkDHNUSQk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=tkWqdSAi6dQ:iHhkDHNUSQk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=tkWqdSAi6dQ:iHhkDHNUSQk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=tkWqdSAi6dQ:iHhkDHNUSQk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=tkWqdSAi6dQ:iHhkDHNUSQk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=tkWqdSAi6dQ:iHhkDHNUSQk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=tkWqdSAi6dQ:iHhkDHNUSQk:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/tkWqdSAi6dQ" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/articles/what-are-you-using/feed/</wfw:commentRss> <slash:comments>107</slash:comments> <feedburner:origLink>http://net.tutsplus.com/articles/what-are-you-using/</feedburner:origLink></item> <item><title>Parallel Testing for PHPUnit with ParaTest</title><link>http://feedproxy.google.com/~r/nettuts/~3/d7vsCtgAclM/</link> <comments>http://net.tutsplus.com/tutorials/php/parallel-testing-for-phpunit-with-paratest/#comments</comments> <pubDate>Thu, 06 Jun 2013 21:27:38 +0000</pubDate> <dc:creator>Brian Scaturro</dc:creator> <category><![CDATA[PHP]]></category> <category><![CDATA[phpunit]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32105</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32105&amp;c=725415555' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32105&amp;c=725415555' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;PHPUnit has hinted at parallelism since 2007, but, in the meantime, our tests continue to run slowly. Time is money, right? ParaTest is a tool that sits on top of PHPUnit and allows you to run tests in parallel without the use of extensions. This is an  ideal candidate for functional (i.e Selenium) tests and other long-running processes.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-32105"&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;ParaTest at your Service&lt;/h2&gt;&lt;p&gt;ParaTest is a robust command line tool for running PHPUnit tests in parallel. Inspired by the fine folks at &lt;a
href="https://saucelabs.com/" target="_blank"&gt;Sauce Labs&lt;/a&gt;, it was originally developed to be a more complete solution for improving the speed of functional tests.&lt;/p&gt;&lt;p&gt;Since its inception &amp;#8211; and thanks to some brilliant contributors (including Giorgio Sironi, the maintainer of the PHPUnit Selenium extension) &amp;#8211; ParaTest has become a valuable tool for speeding up functional tests, as well as integration tests involving databases, web services, and file systems.&lt;/p&gt;&lt;p&gt;ParaTest also has the honor of being bundled with Sauce Labs&amp;#8217; testing framework &lt;a
href="https://github.com/jlipps/sausage" target="_blank"&gt;Sausage&lt;/a&gt;, and has been used in nearly 7000 projects, at the time of this writing.&lt;/p&gt;&lt;h3&gt;Installing ParaTest&lt;/h3&gt;&lt;p&gt;Currently, the only official way to install ParaTest is through &lt;a
href="https://github.com/composer/composer" target="_blank"&gt;Composer&lt;/a&gt;. For those of you who are new to Composer, we have a great &lt;a
href="http://net.tutsplus.com/tutorials/php/easy-package-management-with-composer/" target="_blank"&gt;article&lt;/a&gt; on the subject. To fetch the latest development version, include the following within your &lt;code&gt;composer.json&lt;/code&gt; file:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
&amp;quot;require&amp;quot;: {
    &amp;quot;brianium/paratest&amp;quot;: &amp;quot;dev-master&amp;quot;
}
&lt;/pre&gt;&lt;p&gt;Alternatively, for the latest stable version:&lt;/p&gt;&lt;pre class="brush: jscript; title: ; notranslate"&gt;
&amp;quot;require&amp;quot;: {
    &amp;quot;brianium/paratest&amp;quot;: &amp;quot;0.4.4&amp;quot;
}
&lt;/pre&gt;&lt;p&gt;Next, run &lt;code&gt;composer install&lt;/code&gt; from the command line. The ParaTest binary will be created in the &lt;code&gt;vendor/bin&lt;/code&gt; directory.&lt;/p&gt;&lt;h3&gt;The ParaTest Command Line Interface&lt;/h3&gt;&lt;p&gt;ParaTest includes a command line interface that should be familiar to most PHPUnit users &amp;#8211; with some added bonuses for parallel testing.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/05/paratest-usage.jpg" border="0" alt="ParaTest CLI" title="ParaTest CLI" /&gt;&lt;/figure&gt;&lt;h3&gt;Your First Parallel Test&lt;/h3&gt;&lt;p&gt;Using ParaTest is just as simple as PHPUnit. To quickly demonstrate this in action, create a directory, &lt;code&gt;paratest-sample&lt;/code&gt;, with the following structure:&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/05/structure.jpg" alt="sample directory structure" border="0" title="sample directory structure" /&gt;&lt;/figure&gt;&lt;p&gt;Let&amp;#8217;s install ParaTest as mentioned above. Assuming that you have a Bash shell and a globally installed Composer binary, you can accomplish this in one line from the &lt;code&gt;paratest-sample&lt;/code&gt; directory:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;
echo '{&amp;quot;require&amp;quot;: { &amp;quot;brianium/paratest&amp;quot;: &amp;quot;0.4.4&amp;quot; }}' &amp;gt; composer.json &amp;amp;&amp;amp; composer install
&lt;/pre&gt;&lt;p&gt;For each of the files in the directory, create a test case class with the same name, like so:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
class SlowOneTest extends PHPUnit_Framework_TestCase
{
    public function test_long_running_condition()
    {
        sleep(5);
        $this-&amp;gt;assertTrue(true);
    }
}
&lt;/pre&gt;&lt;p&gt;Take note of the use of &lt;code&gt;sleep(5)&lt;/code&gt; to simulate a test that will take five seconds to execute. So we should have five test cases that each take five seconds to run. Using vanilla PHPUnit, these tests will run serially and take twenty-five seconds, total. ParaTest will run these tests concurrently in five separate processes and should only take five seconds, not twenty-five!&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/05/paratestvsphpunit.jpg" border="0" title="ParaTest vs Vanilla PHPUnit" alt="ParaTest vs Vanilla PHPUnit" /&gt;&lt;/figure&gt;&lt;p&gt;Now that we have an understanding of what ParaTest is, let&amp;#8217;s dig a little deeper into the problems associated with running PHPUnit tests in parallel.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;The Problem at Hand&lt;/h2&gt;&lt;p&gt;Testing can be a slow process, especially when we start talking about hitting a database or automating a browser. In order to test more quickly and efficiently, we need to be able to run our tests concurrently (at the same time), instead of serially (one after the other).&lt;/p&gt;&lt;p&gt;The general method for accomplishing this is not a new idea: run different test groups in multiple PHPUnit processes. This can easily be accomplished using the native PHP function &lt;code&gt;proc_open&lt;/code&gt;. The following would be an example of this in action:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
/**
 * $runningTests - currently open processes
 * $loadedTests - an array of test paths
 * $maxProcs - the total number of processes we want running
 */
while(sizeof($runningTests) || sizeof($loadedTests)) {
    while(sizeof($loadedTests) &amp;amp;&amp;amp; sizeof($runningTests) &amp;lt; $maxProcs)
        $runningTests[] = proc_open(&amp;quot;phpunit &amp;quot; . array_shift($loadedTests), $descriptorspec, $pipes);
    //log results and remove any processes that have finished ....
}
&lt;/pre&gt;&lt;p&gt; Because PHP lacks native threads, this is a typical method for acheiving some level of concurrency. The particular challenges of testing tools that use this method can be boiled down to three core problems:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;How do we load tests?&lt;/li&gt;&lt;li&gt;How do we aggregate and report results from the different PHPUnit processes?&lt;/li&gt;&lt;li&gt;How can we provide consistency with the original tool (i.e PHPUnit)?&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; Let&amp;#8217;s look at a few techniques that have been employed in the past, and then review ParaTest and how it differs from the rest of the crowd.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Those Who Came Before&lt;/h2&gt;&lt;p&gt;As noted earlier, the idea of running PHPUnit in multiple processes is not a new one. The typical procedure employed is something along the following lines:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Grep for test methods or load a directory of files containing test suites.&lt;/li&gt;&lt;li&gt;Open a process for each test method or suite.&lt;/li&gt;&lt;li&gt;Parse output from STDOUT pipe.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Let&amp;#8217;s take a look at a tool that employs this method.&lt;/p&gt;&lt;h3&gt;Hello, &lt;a
href="https://github.com/jlipps/paraunit" target="_blank"&gt;Paraunit&lt;/a&gt;&lt;/h3&gt;&lt;p&gt; Paraunit was the original parallel runner bundled with Sauce Labs&amp;#8217; &lt;a
href="https://github.com/jlipps/sausage" target="_blank"&gt;Sausage&lt;/a&gt; tool, and it served as the starting point for ParaTest. Let&amp;#8217;s look at how it tackles the three main problems mentioned above.&lt;/p&gt;&lt;h4&gt;Test Loading&lt;/h4&gt;&lt;p&gt; Paraunit was designed to ease functional testing. It executes each test method rather than an entire test suite in a PHPUnit process of its very own. Given the path to a collection of tests, Paraunit searches for individual test methods, via pattern matching against file contents.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
preg_match_all(&amp;quot;/function (test[^\(]+)\(/&amp;quot;, $fileContents, $matches);
&lt;/pre&gt;&lt;p&gt;Loaded test methods can then be run like so:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
proc_open(&amp;quot;phpunit --filter=$testName $testFile&amp;quot;, $descriptorspec, $pipes);
&lt;/pre&gt;&lt;p&gt;In a test where each method is setting up and tearing down a browser, this can make things quite a bit faster, if each of those methods is run in a separate process. However, there are a couple of problems with this method.&lt;/p&gt;&lt;p&gt;While methods that begin with the word, &amp;#8220;&lt;em&gt;test&lt;/em&gt;,&amp;#8221; is a strong convention among PHPUnit users, annotations are another option. The loading method used by Paraunit would skip this perfectly valid test:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
/**
 * @test
 */
public function twoTodosCheckedShowsCorrectClearButtonText()
{
    $this-&amp;gt;todos-&amp;gt;addTodos(array('one', 'two'));
    $this-&amp;gt;todos-&amp;gt;getToggleAll()-&amp;gt;click();
    $this-&amp;gt;assertEquals('Clear 2 completed items', $this-&amp;gt;todos-&amp;gt;getClearButton()-&amp;gt;text());
}
&lt;/pre&gt;&lt;p&gt;In addition to not supporting test annotations, inheritance is also limited. We might argue the merits of doing something like this, but let&amp;#8217;s consider the following setup:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
abstract class TodoTest extends PHPUnit_Extensions_Selenium2TestCase
{
    protected $browser = null;

    public function setUp()
    {
       //configure browser
    }

    public function testTypingIntoFieldAndHittingEnterAddsTodo()
    {
        //selenium magic
    }
}

/**
 * ChromeTodoTest.php
 * No test methods to read!
 */
class ChromeTodoTest extends TodoTest
{
    protected $browser = 'chrome';
}

/**
 * FirefoxTodoTest.php
 * No test methods to read!
 */
class FirefoxTodoTest extends TodoTest
{
    protected $browser = 'firefox';
}
&lt;/pre&gt;&lt;p&gt;The inherited methods aren&amp;#8217;t in the file, so they will never be loaded.&lt;/p&gt;&lt;h4&gt;Displaying Results&lt;/h4&gt;&lt;p&gt;Paraunit aggregates the results of each process by parsing the output generated by each process. This method allows Paraunit to capture the full gamut of short codes and feedback presented by PHPUnit.&lt;/p&gt;&lt;p&gt;The downside to aggregating results this way is that it is pretty unwieldy and easy to break. There are a lot of different outcomes to account for, and a lot of regular expressions at work to display meaningful results in this way.&lt;/p&gt;&lt;h4&gt;Consistency with PHPUnit&lt;/h4&gt;&lt;p&gt; Due to the file grepping, Paraunit is fairly limited in what PHPUnit features it can support. It&amp;#8217;s an excellent tool for running a simple structure of functional tests, but, in addition to some of the difficulties mentioned already, it lacks support for some useful PHPUnit features. Some such examples include test suites, specifying configuration and bootstrap files, logging results, and running specific test groups.&lt;/p&gt;&lt;p&gt;Many of the existing tools follow this pattern. Grep a directory of test files and either run the entire file in a new process or each method &amp;#8211; never both.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;ParaTest At Bat&lt;/h2&gt;&lt;p&gt; The goal of ParaTest is to support parallel testing for a variety of scenarios. Originally created to fill the gaps in Paraunit, it has become a robust command line tool for running both test suites and test methods in parallel. This makes ParaTest an ideal candidate for long running tests of different shapes and sizes.&lt;/p&gt;&lt;h3&gt;How ParaTest Handles Parallel Testing&lt;/h3&gt;&lt;p&gt;ParaTest deviates from the established norm in order to support more of PHPUnit, and acts as a truly viable candidate for parallel testing.&lt;/p&gt;&lt;h4&gt;Test Loading&lt;/h4&gt;&lt;p&gt; ParaTest loads tests in a similar manner to PHPUnit. It loads all tests in a specified directory that end with the &lt;code&gt;*Test.php&lt;/code&gt; suffix, or will load tests based on the standard PHPUnit XML configuration file. Loading is accomplished, via reflection, so it is easy to support &lt;code&gt;@test&lt;/code&gt; methods, inheritance, test suites and individual test methods. Reflection makes adding support for other annotations a snap.&lt;/p&gt;&lt;p&gt;Because reflection allows ParaTest to grab classes and methods, it can run both test suites and test methods in parallel, making it a more versatile tool.&lt;/p&gt;&lt;p&gt;ParaTest does impose some constraints, but well-founded ones in the PHP community. Tests do need to follow the &lt;a
href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md" target="_blank"&gt;PSR-0 standard&lt;/a&gt;, and the default file suffix of &lt;code&gt;*Test.php&lt;/code&gt; is not configurable, as it is in PHPUnit. There is a current branch in progress for supporting the same suffix configuration allowed in PHPUnit.&lt;/p&gt;&lt;h4&gt;Displaying Results&lt;/h4&gt;&lt;p&gt; ParaTest also deviates from the path of parsing STDOUT pipes. Instead of parsing output streams, ParaTest logs the results of each PHPUnit process in the JUnit format and aggregates results from these logs. It&amp;#8217;s much easier to read test results from an established format than an output stream.&lt;/p&gt;&lt;pre class="brush: xml; title: ; notranslate"&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;testsuites&amp;gt;
  &amp;lt;testsuite name=&amp;quot;AnotherUnitTestInSubLevelTest&amp;quot; file=&amp;quot;/home/brian/Projects/parallel-phpunit/test/fixtures/tests/level1/AnotherUnitTestInSubLevelTest.php&amp;quot; tests=&amp;quot;3&amp;quot; assertions=&amp;quot;3&amp;quot; failures=&amp;quot;0&amp;quot; errors=&amp;quot;0&amp;quot; time=&amp;quot;0.005295&amp;quot;&amp;gt;
    &amp;lt;testcase name=&amp;quot;testTruth&amp;quot; class=&amp;quot;AnotherUnitTestInSubLevelTest&amp;quot; file=&amp;quot;/home/brian/Projects/parallel-phpunit/test/fixtures/tests/level1/AnotherUnitTestInSubLevelTest.php&amp;quot; line=&amp;quot;7&amp;quot; assertions=&amp;quot;1&amp;quot; time=&amp;quot;0.001739&amp;quot;/&amp;gt;
    &amp;lt;testcase name=&amp;quot;testFalsehood&amp;quot; class=&amp;quot;AnotherUnitTestInSubLevelTest&amp;quot; file=&amp;quot;/home/brian/Projects/parallel-phpunit/test/fixtures/tests/level1/AnotherUnitTestInSubLevelTest.php&amp;quot; line=&amp;quot;15&amp;quot; assertions=&amp;quot;1&amp;quot; time=&amp;quot;0.000477&amp;quot;/&amp;gt;
    &amp;lt;testcase name=&amp;quot;testArrayLength&amp;quot; class=&amp;quot;AnotherUnitTestInSubLevelTest&amp;quot; file=&amp;quot;/home/brian/Projects/parallel-phpunit/test/fixtures/tests/level1/AnotherUnitTestInSubLevelTest.php&amp;quot; line=&amp;quot;23&amp;quot; assertions=&amp;quot;1&amp;quot; time=&amp;quot;0.003079&amp;quot;/&amp;gt;
  &amp;lt;/testsuite&amp;gt;
&amp;lt;/testsuites&amp;gt;
&lt;/pre&gt;&lt;p&gt; Parsing JUnit logs does have some minor drawbacks. Skipped and ignored tests are not reported in the immediate feedback, but they  will be reflected in the totaled values displayed after a test run.&lt;/p&gt;&lt;h4&gt;Consistency with PHPUnit&lt;/h4&gt;&lt;p&gt;Reflection allows ParaTest to support more PHPUnit conventions. The ParaTest console supports more PHPUnit features out of the box than any other similar tool, such as the ability to run groups, supply configuration and bootstrap files, and log results in the JUnit format.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;ParaTest Examples&lt;/h2&gt;&lt;p&gt; ParaTest can be used to gain speed in several testing scenarios.&lt;/p&gt;&lt;h3&gt;Functional Testing With Selenium&lt;/h3&gt;&lt;p&gt; ParaTest excels at functional testing. It supports a &lt;code&gt;-f&lt;/code&gt; switch in its console to enable functional mode. Functional mode instructs ParaTest to run each test method in a separate process, instead of the default, which is to run each test suite in a separate process.&lt;/p&gt;&lt;p&gt;It&amp;#8217;s often the case that each functional test method does a lot of work, such as opening a browser, navigating around the page, and then closing the browser.&lt;/p&gt;&lt;p&gt;The example project, &lt;a
href="https://github.com/brianium/paratest-selenium" target="_blank"&gt;paratest-selenium&lt;/a&gt;, demonstrates testing a Backbone.js todo application with Selenium and ParaTest. Each test method opens a browser and tests a specific feature:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
public function setUp()
{
    $this-&amp;gt;setBrowserUrl('http://backbonejs.org/examples/todos/');
    $this-&amp;gt;todos = new Todos($this-&amp;gt;prepareSession());
}

public function testTypingIntoFieldAndHittingEnterAddsTodo()
{
    $this-&amp;gt;todos-&amp;gt;addTodo(&amp;quot;parallelize phpunit tests\n&amp;quot;);
    $this-&amp;gt;assertEquals(1, sizeof($this-&amp;gt;todos-&amp;gt;getItems()));
}

public function testClickingTodoCheckboxMarksTodoDone()
{
    $this-&amp;gt;todos-&amp;gt;addTodo(&amp;quot;make sure you can complete todos&amp;quot;);
    $items = $this-&amp;gt;todos-&amp;gt;getItems();
    $item = array_shift($items);
    $this-&amp;gt;todos-&amp;gt;getItemCheckbox($item)-&amp;gt;click();
    $this-&amp;gt;assertEquals('done', $item-&amp;gt;attribute('class'));
}

//....more tests
&lt;/pre&gt;&lt;p&gt;This test case could take a hot second if it were to run serially, via vanilla PHPUnit. Why not run multiple methods at once?&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/05/terminal.jpg" border="0" alt="running selenium tests with ParaTest" title="running selenium tests with ParaTest" /&gt;&lt;/figure&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/05/manychromes.jpg" border="0" title="ParaTest automating selenium tests in 5 processes" alt="Many chrome instances running functional tests" /&gt;&lt;/figure&gt;&lt;h3&gt;Handling Race Conditions&lt;/h3&gt;&lt;p&gt;As with any parallel testing, we have to be mindful of scenarios that will present race conditions &amp;#8211; such as multiple processes trying to access a database. The dev-master branch of ParaTest sports a really handy test token feature, written by collaborator Dimitris Baltas (dbaltas on Github), that makes integration testing databases much easier.&lt;/p&gt;&lt;p&gt;Dimitris has included a helpful example that demonstrates this feature on &lt;a
href="https://github.com/tripsta/paratest-sample" target="_blank"&gt;Github&lt;/a&gt;. In Dimitris&amp;#8217; own words:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; &lt;code&gt;TEST_TOKEN&lt;/code&gt; attempts to deal with the common resources issue in a very simple way: clone the resources to ensure that no concurrent processes will access the same resource.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;A &lt;code&gt;TEST_TOKEN&lt;/code&gt; environment variable is provided for tests to consume ,and is recycled when the process has finished. It can be used to conditionally alter your tests, like so:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
public function setUp()
{
    parent::setUp();
    $this-&amp;gt;_filename = sprintf('out%s.txt', getenv('TEST_TOKEN'));
}
&lt;/pre&gt;&lt;h3&gt;ParaTest and Sauce Labs&lt;/h3&gt;&lt;p&gt;&lt;a
href="https://saucelabs.com/" target="_blank"&gt;Sauce Labs&lt;/a&gt; is the Excalibur of functional testing. Sauce Labs provides a service that allows you to easily test your applications in a variety of browsers and platforms. If you haven&amp;#8217;t checked them out before, I strongly encourage you to do so.&lt;/p&gt;&lt;p&gt;Testing with Sauce could be a tutorial in itself, but those wizards have already done a great job of providing &lt;a
href="https://saucelabs.com/php/se2/1" target="_blank"&gt;tutorials&lt;/a&gt; for using PHP and ParaTest to write functional tests using their service.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;The Future of ParaTest&lt;/h2&gt;&lt;p&gt;ParaTest is a great tool for filling in some of the gaps of PHPUnit, but, ultimately, it&amp;#8217;s just a plug in the dam. A much better scenario would be native support in PHPUnit!&lt;/p&gt;&lt;p&gt;In the meantime, ParaTest will continue increasing support for more of PHPUnit&amp;#8217;s native behavior. It will continue to offer features that are helpful to parallel testing &amp;#8211; particularly in the functional and integration realms.&lt;/p&gt;&lt;p&gt; ParaTest has many great things in the works to beef up the transparency between PHPUnit and itself, primarily in what configuration options are supported.&lt;/p&gt;&lt;p&gt;The latest stable version of ParaTest (v0.4.4) comfortably supports Mac, Linux, and Windows, but there are some valuable pull requests and features in &lt;code&gt;dev-master&lt;/code&gt; that definitely cater to the Mac and Linux crowds. So that will be an interesting conversation moving forward.&lt;/p&gt;&lt;h3&gt;Additional Reading and Resources&lt;/h3&gt;&lt;p&gt;There are a handful of articles and resources around the web that feature ParaTest. Give them a read, if you&amp;#8217;re interested:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a
href="https://github.com/brianium/paratest"&gt;ParaTest on Github&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a
href="http://css.dzone.com/articles/parallel-phpunit" target="_blank"&gt;Parallel PHPUnit&lt;/a&gt; by ParaTest contributor and PHPUnit Selenium extension maintainer Giorgio Sironi&lt;/li&gt;&lt;li&gt;&lt;a
href="http://css.dzone.com/articles/contributing-paratest" target="_blank"&gt;Contributing to Paratest&lt;/a&gt;. An excellent article on Giorgio&amp;#8217;s experimental WrapperRunner for ParaTest&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/giorgiosironi/paratest/tree/reuse_bootstrap"&gt;Giorgio&amp;#8217;s WrapperRunner Source Code&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/tripsta/paratest-sample" target="_blank"&gt;tripsta/paratest-sample&lt;/a&gt;. An example of the TEST_TOKEN feature by it&amp;#8217;s creator Dimitris Baltas&lt;/li&gt;&lt;li&gt;&lt;a
href="https://github.com/brianium/paratest-selenium" target="_blank"&gt;brianium/paratest-selenium&lt;/a&gt;. An example of using ParaTest to write functional tests&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=d7vsCtgAclM:bXTToDil-Gk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=d7vsCtgAclM:bXTToDil-Gk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=d7vsCtgAclM:bXTToDil-Gk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=d7vsCtgAclM:bXTToDil-Gk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=d7vsCtgAclM:bXTToDil-Gk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=d7vsCtgAclM:bXTToDil-Gk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=d7vsCtgAclM:bXTToDil-Gk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=d7vsCtgAclM:bXTToDil-Gk:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/d7vsCtgAclM" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/php/parallel-testing-for-phpunit-with-paratest/feed/</wfw:commentRss> <slash:comments>7</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/php/parallel-testing-for-phpunit-with-paratest/</feedburner:origLink></item> <item><title>Whoops! PHP Errors for Cool Kids</title><link>http://feedproxy.google.com/~r/nettuts/~3/xRKk1iql0T8/</link> <comments>http://net.tutsplus.com/tutorials/php/whoops-php-errors-for-cool-kids/#comments</comments> <pubDate>Wed, 05 Jun 2013 14:56:14 +0000</pubDate> <dc:creator>Filipe Dobreira</dc:creator> <category><![CDATA[PHP]]></category> <category><![CDATA[whoops]]></category> <guid isPermaLink="false">http://net.tutsplus.com/?p=32344</guid> <description>&lt;a
href='http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32344&amp;c=539357740' target='_blank'&gt;&lt;img
src='http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=32344&amp;c=539357740' border='0' alt='' /&gt;&lt;/a&gt;&lt;p&gt;&lt;a
href="http://filp.github.io/whoops/"&gt;Whoops&lt;/a&gt; is a small library, available as a &lt;a
href="https://packagist.org/packages/filp/whoops"&gt;Composer package&lt;/a&gt;, that helps you handle errors and exceptions across your PHP projects.&lt;/p&gt;&lt;p&gt;&lt;span
id="more-32344"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Out of the box, you get a sleek, intuitive and informative error page each time something goes pants-up in your application. Even better, under all that is a very straight-forward, but flexible, toolset for dealing with errors in a way that makes sense for whatever it is that you&amp;#8217;re doing.&lt;/p&gt;&lt;p&gt;The library&amp;#8217;s main features are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Detailed and intuitive page for errors and exceptions&lt;/li&gt;&lt;li&gt;Code view for all frames&lt;/li&gt;&lt;li&gt;Focus on error/exception analysis through the use of custom, simple middle-ware/handlers&lt;/li&gt;&lt;li&gt;Support for JSON and AJAX requests&lt;/li&gt;&lt;li&gt;Included providers for Silex and Zend projects through the bundled providers, and included as part of the Laravel 4 core&lt;/li&gt;&lt;li&gt;Clean, compact, and tested code-base, with no extra dependencies&lt;/li&gt;&lt;/ul&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-demo.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;Whoops achieves this through a system of stacked handlers. You tell Whoops which handlers you want to use (you can choose from the included handlers or make your own), and if something happens, all the handlers are given, in order, a chance do to something &amp;#8211; this can be anything from analyzing the error (Whoops makes it easier to extract meaningful information from an error or exception), to displaying helpful error screens (like the built-in &lt;code&gt;PrettyPageHandler&lt;/code&gt;, which gives you the cool looking page pictured above).&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s give it a try, first, by looking at the basics, and then by having a go at building our own handler with Whoops and the Laravel framework. For this short guide, I&amp;#8217;ll assume that  you&amp;#8217;re moderately comfortable with PHP, and that you&amp;#8217;ve heard of Composer. If this is not the case, read-up on it &lt;a
href="http://net.tutsplus.com/tutorials/php/easy-package-management-with-composer."&gt;here at Nettuts+&lt;/a&gt;.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Installing Whoops&lt;/h2&gt;&lt;p&gt;Create a directory for your project, change into it, create a &lt;code&gt;composer.json&lt;/code&gt; file with the Whoops requirement, and install it. Whoops (as of version 1.0.5) has no dependencies, so this will only take a second.&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;
$ cd /path/to/your/project
$ composer require filp/whoops 1.*
$ composer install
&lt;/pre&gt;&lt;hr
/&gt;&lt;h2&gt;Using Whoops: The Basics&lt;/h2&gt;&lt;p&gt;To see that sleek error page in action, let&amp;#8217;s setup Whoops and ensure that something breaks by throwing an exception within our code. Create a file within your project&amp;#8217;s directory; for this guide, let&amp;#8217;s say that it&amp;#8217;s called, &lt;code&gt;index.php&lt;/code&gt;.&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;
$ cd /path/to/your/project
$ your-favorite-editor index.php
&lt;/pre&gt;&lt;p&gt;Because we installed Whoops with Composer, and it is PSR-0 compliant, all we need to do is require the Composer autoloader and we&amp;#8217;re ready to start using the library within our own code!&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
# index.php
require __DIR__ . &amp;quot;/vendor/autoload.php&amp;quot;;

$whoops = new Whoops\Run();
$whoops-&amp;gt;pushHandler(new Whoops\Handler\PrettyPageHandler());

// Set Whoops as the default error and exception handler used by PHP:
$whoops-&amp;gt;register();  

throw new RuntimeException(&amp;quot;Oopsie!&amp;quot;);
?&amp;gt;

&lt;/pre&gt;&lt;p&gt;If you already have a web-server running, go ahead and access the file that you just created. Don&amp;#8217;t forget: if you&amp;#8217;re using PHP 5.4, you can leverage the built-in development server, like so:&lt;/p&gt;&lt;pre class="brush: bash; title: ; notranslate"&gt;
$ cd /path/to/your/project
$ php -S localhost:8080
&lt;/pre&gt;&lt;p&gt;This is what you&amp;#8217;ll get:&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-basic.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;Pretty neat, right? Handlers, themselves, can expose options to modify or augment their behavior. For example, among other things, you can set the title of the default error page, and even insert extra information:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
# index.php
$whoops = new Whoops\Run();

// Configure the PrettyPageHandler:
$errorPage = new Whoops\Handler\PrettyPageHandler();

$errorPage-&amp;gt;setPageTitle(&amp;quot;It's broken!&amp;quot;); // Set the page's title
$errorPage-&amp;gt;setEditor(&amp;quot;sublime&amp;quot;);         // Set the editor used for the &amp;quot;Open&amp;quot; link
$errorPage-&amp;gt;addDataTable(&amp;quot;Extra Info&amp;quot;, array(
      &amp;quot;stuff&amp;quot;     =&amp;gt; 123,
      &amp;quot;foo&amp;quot;       =&amp;gt; &amp;quot;bar&amp;quot;,
      &amp;quot;useful-id&amp;quot; =&amp;gt; &amp;quot;baloney&amp;quot;
));

$whoops-&amp;gt;pushHandler($errorPage);
$whoops-&amp;gt;register();

throw new RuntimeException(&amp;quot;Oopsie!&amp;quot;);
?&amp;gt;
&lt;/pre&gt;&lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-extra-info.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;Also, since this is simply a regular Whoops handler, we can mix-and-match with other handlers to achieve more dynamic results. Let&amp;#8217;s imagine that you&amp;#8217;re working on an AJAX+JSON-driven website. Right now, if your application were to fail somehow, you would get a bunch of nasty HTML coming down the pipe, when you were expecting JSON. No big deal:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
# index.php
$whoops-&amp;gt;pushHandler(new Whoops\Handler\PrettyPageHandler());
$whoops-&amp;gt;pushHandler(new Whoops\Handler\JsonResponseHandler());

$whoops-&amp;gt;register();

throw new RuntimeException(&amp;quot;Oopsie!&amp;quot;);
&lt;/pre&gt;&lt;p&gt;That&amp;#8217;s it. Now, if something fails during an AJAX request, Whoops will respond with a JSON response detailing the error. If it&amp;#8217;s NOT an AJAX request, you will continue to see the regular error page. If an error ocurrs, Whoops will filter through each of the registered handlers (starting at the last handler to be registered), and give them a chance to analyze, modify and respond to the request.&lt;/p&gt;&lt;p&gt;Now that you have a general idea of how Whoops works, let&amp;#8217;s have a go at building our own handler with Whoops and the &lt;a
href="http://laravel.com"&gt;Laravel 4&lt;/a&gt; framework.&lt;/p&gt;&lt;hr
/&gt;&lt;h2&gt;Whoops and Laravel 4&lt;/h2&gt;&lt;p&gt;Laravel 4 bundles Whoops as a core exception handler, enabled by default in development mode, including a custom color-scheme by &lt;a
href="http://twitter.com/daylerees"&gt;Dayle Rees&lt;/a&gt;:&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-laravel.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;If you haven&amp;#8217;t installed Laravel yet, &lt;a
href="http://laravel.com"&gt;head on over&lt;/a&gt; and follow the installation steps. Laravel is covered extensively on &lt;a
href="http://net.tutsplus.com/?s=laravel"&gt;Nettuts+&lt;/a&gt; and &lt;a
href="https://tutsplus.com/course/whats-new-in-laravel-4/"&gt;Tuts+ Premium&lt;/a&gt;, so you&amp;#8217;ll find plenty of training here, if you&amp;#8217;d like to dig in further.&lt;/p&gt;&lt;p&gt;For the next steps, I&amp;#8217;ll assume that you are somewhat comfortable with the basics of Laravel 4. However, even if you aren&amp;#8217;t, it should still be easy to follow.&lt;/p&gt;&lt;p&gt;If you&amp;#8217;re in development (debug) mode, Whoops is available through the IoC container as &lt;code&gt;whoops&lt;/code&gt;, and pre-set with one of two handlers: &lt;code&gt;PrettyPageHandler&lt;/code&gt; or &lt;code&gt;JsonResponseHandler&lt;/code&gt;, as &lt;code&gt;whoops.handler&lt;/code&gt; (the same two we just talked about). Both of these handlers expose useful additional methods, as you&amp;#8217;ve seen above with the &lt;code&gt;PrettyPageHandler&lt;/code&gt;. By accessing these services, we can start customizing our Whoops experience within the framework.&lt;/p&gt;&lt;p&gt;For simplicity&amp;#8217;s sake, in your &lt;code&gt;app/routes.php&lt;/code&gt; file, let&amp;#8217;s hook into the Whoops service and set a custom page title for our error pages:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
#app/routes.php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
*/

use Whoops\Handler\PrettyPageHandler;

// Use the Laravel IoC container to get the Whoops\Run instance, if whoops
// is available (which will be the case, by default, in the dev
// environment)
if(App::bound(&amp;quot;whoops&amp;quot;)) {
    // Retrieve the whoops handler in charge of displaying exceptions:
    $whoopsDisplayHandler = App::make(&amp;quot;whoops.handler&amp;quot;);

    // Laravel will use the PrettyPageHandler by default, unless this
    // is an AJAX request, in which case it'll use the JsonResponseHandler:
    if($whoopsDisplayHandler instanceof PrettyPageHandler) {

        // Set a custom page title for our error page:
        $whoopsDisplayHandler-&amp;gt;setPageTitle(&amp;quot;Houston, we've got a problem!&amp;quot;);

        // Set the &amp;quot;open:&amp;quot; link for files to our editor of choice:
        $whoopsDisplayHandler-&amp;gt;setEditor(&amp;quot;sublime&amp;quot;);
    }
}

Route::get('/', function()
{
    // Force the execution to fail by throwing an exception:
    throw new RuntimeException(&amp;quot;Oopsie!&amp;quot;);
});
?&amp;gt;

&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Whoops supports a few editors by default, and allows you to implement support for your own as you wish. &lt;a
href="https://github.com/filp/whoops#opening-referenced-files-with-your-favorite-editor-or-ide"&gt;Read more about it here.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If you now access your Laravel application, you&amp;#8217;ll be greeted with an error message with your custom page title. If you click the file path above the code box, it should open the referenced file right in your editor or IDE of choice. How cool is that? Also, since we can reach the handler already setup by the Laravel core, we can put to use the other features we&amp;#8217;ve learned about above. For example, we can add custom tables (with &lt;code&gt;PrettyPageHandler::addDataTable&lt;/code&gt;) with useful information about our application.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s have a go at one more example. This will be our first attempt at writing our own custom handler. We want to get all the stack frames for an exception, and remove anything that&amp;#8217;s not part of our application code. Sounds simple enough, right?&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
#app/routes.php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
*/

use Whoops\Handler\Handler;

// Use the Laravel IoC to get the Whoops\Run instance, if whoops
// is available (which will be the case, by default, in the dev
// environment)
if(App::bound(&amp;quot;whoops&amp;quot;)) {
    $whoops = App::make(&amp;quot;whoops&amp;quot;);

    $whoops-&amp;gt;pushHandler(function($exception, $exceptionInspector, $runInstance) {
        // Get the collection of stack frames for the current exception:
        $frames = $exceptionInspector-&amp;gt;getFrames();

        // Filter existing frames so we only keep the ones inside the app/ folder
        $frames-&amp;gt;filter(function($frame) {
            $filePath = $frame-&amp;gt;getFile();

            // Match any file path containing /app/...
            return preg_match(&amp;quot;/\/app\/.+/i&amp;quot;, $filePath);
        });

        return Handler::DONE;
    });
}

Route::get('/', function()
{
    // Force the execution to fail by throwing an exception:
    throw new RuntimeException(&amp;quot;Oopsie!&amp;quot;);
});
?&amp;gt;

&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; You don&amp;#8217;t actually have to return &lt;code&gt;Handler::DONE&lt;/code&gt; &amp;#8211; this serves only a semantic purpose. If you want Whoops to stop running any extra handlers after yours, write &lt;code&gt;return Handler::LAST_HANDLER&lt;/code&gt;. If you want Whoops to exit the script execution after your handler, &lt;code&gt;return Handler::QUIT&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;You can see that it&amp;#8217;s remarkably concise. &lt;code&gt;Whoops\Run&lt;/code&gt;&amp;#8216;s &lt;code&gt;pushHandler&lt;/code&gt; method accepts a closure that receives up to three arguments: the exception object, an exception inspector, which exposes some utility methods to, you guessed it, inspect exceptions, and the &lt;code&gt;Whoops\Run&lt;/code&gt; instance that captured the exception. Through this handler, we use the exception inspector to extract the stack frames, all within a neat &lt;code&gt;FrameCollection&lt;/code&gt; object:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
$frames = $exceptionInspector-&amp;gt;getFrames(); // #=&amp;gt; Whoops\Exception\FrameCollection;
count($frames); #=&amp;gt; int

foreach($frames as $frame) {
    get_class($frame); // #=&amp;gt; Whoops\Exception\Frame

    print $frame-&amp;gt;getFile() . &amp;quot;:&amp;quot; . $frame-&amp;gt;getLine() . &amp;quot;\n&amp;quot;;
        #=&amp;gt; &amp;quot;/path/to/file.php:123&amp;quot;
}
?&amp;gt;

&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Whoops internally converts closures to a special handler: &lt;code&gt;Whoops\Handler\CallbackHandler&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;You can count, iterate, map and filter the contents of this class, with the interesting but important aspect that the map and filter operations mutate the object in-place. This means that both of these operations modify the original instance directly, instead of creating a new collection. How is this important? It means handlers can more easily perform changes that propagate downwards to all the other handlers in the stack. This is exactly what we did with our simple handler above. If you now run the script again, you&amp;#8217;ll see that we get a shorter list of stack frames, only concerning the code living within our application directory.&lt;/p&gt; &lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-short-stack.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;As for the Frame object, itself (&lt;code&gt;Whoops\Exception\Frame&lt;/code&gt;), it exposes a set of methods to gather information about the frame contents (the file path, line number, the method or function call, class name, etc,), and methods that allow you to attach comments to individual stack frames. A Frame comment is a useful feature in Whoops that allows handlers to provide additional information that they gather from an exception by attaching notes directly to individual frames in the stack. Handlers like the &lt;code&gt;PrettyPageHandler&lt;/code&gt;, for example, can then gather those comments and display them along with the frame&amp;#8217;s file path and line number.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
$whoops-&amp;gt;pushHandler(function($exception, $exceptionInspector, $runInstance) {
    foreach($exceptionInspector-&amp;gt;getFrames() as $i =&amp;gt; $frame) {
        $frame-&amp;gt;addComment(&amp;quot;This is frame number {$i}&amp;quot;);
    }

    return Handler::DONE;
});
?&amp;gt;

&lt;/pre&gt;&lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-frame-comment.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;Frame comments may also receive a second &lt;code&gt;scope&lt;/code&gt; argument. If you have multiple custom handlers, you can, for example, filter frame comments by this argument to gather only the information that you care about.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
$frames = $exceptionInspector-&amp;gt;getFrames();
foreach($frames as $frame) {
    // Was this frame within a controller class? (ends in Controller)
    $className = $frame-&amp;gt;getClass();
    if(substr($className, -10) == &amp;quot;Controller&amp;quot;) {
        $frame-&amp;gt;addComment(&amp;quot;This frame is inside a controller: $className&amp;quot;, &amp;quot;controller-error&amp;quot;);
    }

    // Later, in another handler, get all comments within the 'controller-errors' scope:
    $controllerErrors = $frame-&amp;gt;getComments(&amp;quot;controller-errors&amp;quot;); // #=&amp;gt; array
}
?&amp;gt;

&lt;/pre&gt;&lt;p&gt;Also of interest, the &lt;code&gt;PrettyPageHandler&lt;/code&gt; naturally HTML-escapes the frame comments before displaying them, but will intelligently capture URIs in the comment&amp;#8217;s body and convert them to clickable anchor elements. Want to link frames to documentation, or to GitHub repositories? It&amp;#8217;s easy enough; let&amp;#8217;s create our own handler class for this example.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Using your own class instead of a closure provides you with some extra control over your handler &amp;#8211; not to mention making it easier to cover with automated tests. Your custom handler classes must implement the &lt;code&gt;Whoops\Handler\HandlerInterface&lt;/code&gt; interface, but you may instead simply extend the &lt;code&gt;Whoops\Handler\Handler&lt;/code&gt; class, and implement the missing &lt;code&gt;handle&lt;/code&gt; method, as shown in the example below.&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
# LaravelGithubLinkHandler.php

use Whoops\Handler\Handler as BaseHandler;

/**
 * When possible, link laravel source files to their location
 * on the laravel/framework repo @ github.com
 */
class LaravelGithubLinkHandler extends BaseHandler
{
    private $repoBase = &amp;quot;https://github.com/laravel/framework/blob/master&amp;quot;;

    /**
     * @return int
     */
    public function handle()
    {
        $frames = $this-&amp;gt;getInspector()-&amp;gt;getFrames();

        foreach($frames as $frame) {
            $file = $frame-&amp;gt;getFile();
            $line = $frame-&amp;gt;getLine();

            // Some frames may not have a file path, for example, if it ocurred within
            // a Closure, so we'll need to check for that:
            if(!$file) continue;

            // Check if the file path for this frame was within the laravel/framework
            // directory, inside the Composer vendor/ directory, and use a regex capture
            // to extract just the parts we want:
            if(preg_match(&amp;quot;/\/vendor\/laravel\/framework\/(.+)$/&amp;quot;, $file, $matches)) {
                $path = $matches[1]; // First match is whole path, second is our capture
                $url  = &amp;quot;{$this-&amp;gt;repoBase}/$path&amp;quot;;

                // We can also link directly to a line number, if we have it. Github
                // supports this by appending #L&amp;lt;line number&amp;gt; to the end of the URL:
                if($line !== null) {
                    $url .= &amp;quot;#L{$line}&amp;quot;;
                }

                $frame-&amp;gt;addComment($url, &amp;quot;github-linker&amp;quot;);
            }
        }

        return Handler::DONE;
    }
}
?&amp;gt;

&lt;/pre&gt;&lt;p&gt;That&amp;#8217;s it, as far as our handler goes. Put that class somewhere in your project, and all that&amp;#8217;s left to do is enable and try it out:&lt;/p&gt;&lt;pre class="brush: php; title: ; notranslate"&gt;
&amp;lt;?php
# app/routes.php
// ...
$whoops-&amp;gt;pushHandler(new LaravelGithubLinkHandler());
// ...
?&amp;gt;

&lt;/pre&gt;&lt;figure
class="tutorial_image"&gt;&lt;img
src="http://cdn.tutsplus.com/net.tutsplus.com/uploads/2013/06/whoops-comment-link.png" alt="image" title="" /&gt;&lt;/figure&gt;&lt;p&gt;With only a handful of lines of code, we&amp;#8217;ve added an extra layer of (possibly useless, but hey, it&amp;#8217;s an example) functionality to our error pages. Here are a few extra ideas, if you&amp;#8217;re looking for a challenge:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Package your custom error handler&lt;/a&gt; as a &lt;a
href="http://laravel.com/docs/ioc#service-providers"&gt;Laravel service provider.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Are you using Git to manage your project? Build a custom handler that hooks into &lt;code&gt;git-blame&lt;/code&gt; to determine who the last person to touch that file that keeps throwing an exception (and yell at them) was, directly from the error page.&lt;/li&gt;&lt;li&gt;If you&amp;#8217;re feeling brave, use nikic&amp;#8217;s &lt;a
href="https://github.com/nikic/PHP-Parser"&gt;PHP-Parser&lt;/a&gt; to analyze the troublesome code, and provide suggestions for fixes (I promise it&amp;#8217;s not as complicated as it sounds).&lt;/li&gt;&lt;/ul&gt;&lt;hr
/&gt;&lt;h2&gt;Final Thoughts&lt;/h2&gt;&lt;p&gt;I hope that this short guide has helped you gain an understanding of the sort of possibilities that this library enables in your every-day projects. For more information, refer to the &lt;a
href="https://github.com/filp/whoops/wiki/API-Documentation"&gt;complete API documentation.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Whoops is framework-agnostic, light-weight and, I believe, quite powerful in its simplicity and focus on mix-and-matching small tools. It&amp;#8217;s also open-source and open to suggestions and improvements. If you&amp;#8217;d like to contribute or report a bug, head to the &lt;a
href="https://github.com/filp/whoops"&gt;official repository&lt;/a&gt;!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=xRKk1iql0T8:W7OlpV-lOOk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=xRKk1iql0T8:W7OlpV-lOOk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=xRKk1iql0T8:W7OlpV-lOOk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=xRKk1iql0T8:W7OlpV-lOOk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=xRKk1iql0T8:W7OlpV-lOOk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=xRKk1iql0T8:W7OlpV-lOOk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?i=xRKk1iql0T8:W7OlpV-lOOk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/nettuts?a=xRKk1iql0T8:W7OlpV-lOOk:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/nettuts?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nettuts/~4/xRKk1iql0T8" height="1" width="1"/&gt;</description> <wfw:commentRss>http://net.tutsplus.com/tutorials/php/whoops-php-errors-for-cool-kids/feed/</wfw:commentRss> <slash:comments>28</slash:comments> <feedburner:origLink>http://net.tutsplus.com/tutorials/php/whoops-php-errors-for-cool-kids/</feedburner:origLink></item> </channel> </rss><!-- Dynamic Page Served (once) in 1.930 seconds -->
