<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[kettle.io Blog]]></title><description><![CDATA[Web development stories and ideas as seen through the eyes of our development team.]]></description><link>https://blog.kettle.io/</link><generator>Ghost 0.9</generator><lastBuildDate>Tue, 24 Mar 2026 14:52:24 GMT</lastBuildDate><atom:link href="https://blog.kettle.io/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Building AWS Lambda apps using Make]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1>

<p>Using <a href="https://aws.amazon.com/lambda/">AWS Lambda</a> we are able to run micro-service sized applications without any traditional server infastruture. These are called "serverless functions", which run inside ephemeral containers that offer several advantages over the traditional server/host configuration. </p>

<p>We've used AWS Lambda functions for some time now. They're a great way</p>]]></description><link>https://blog.kettle.io/building-aws-lambda-apps-using-make/</link><guid isPermaLink="false">0861f131-e1c7-4f49-8e22-83f63a6125db</guid><category><![CDATA[make]]></category><category><![CDATA[lambda]]></category><category><![CDATA[package]]></category><category><![CDATA[nodejs]]></category><dc:creator><![CDATA[Gustavo Straube]]></dc:creator><pubDate>Fri, 28 Jul 2017 15:38:00 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2017/07/sergey-zolkin-21234.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>

<img src="http://blog.kettle.io/content/images/2017/07/sergey-zolkin-21234.jpg" alt="Building AWS Lambda apps using Make"><p>Using <a href="https://aws.amazon.com/lambda/">AWS Lambda</a> we are able to run micro-service sized applications without any traditional server infastruture. These are called "serverless functions", which run inside ephemeral containers that offer several advantages over the traditional server/host configuration. </p>

<p>We've used AWS Lambda functions for some time now. They're a great way to perform a simple computing at a large scale. And the best part - it comes without the need to manage server instances and other resources.</p>

<p>Lambda allows you to write functions in a variety of different langauges (Java, Node.js, C# and Python). Our functions run on NodeJS.</p>

<p>The latest function we're working on has a single third-party library dependency. This adds an additional step to the development process, since we can't simply paste the function code into the inline editor for testing and deployment. The application package must be manually created via CLI - yet after doing that 2 or 3 times it starts to become redundant. Run a command, wait for it to complete, then run the next and so on...</p>

<p>It was time to automate this process. The solution was to use <a href="http://www.gnu.org/software/make/">Make</a>. It's super easy to setup, it's available on Mac and it's grown-up software.</p>

<h2 id="makingthings">Making things</h2>

<p>Our packaging process has the following steps:</p>

<ol>
<li>Remove any old package.  </li>
<li>Install Node non-dev dependencies.  </li>
<li>Package the function and dependencies together.</li>
</ol>

<p>Our <code>Makefile</code> is almost an exact representation of that recipe:</p>

<pre><code>lambda.zip: clean
    rm -rf node_modules/
    npm install --only=production
    zip -r $@ lambda.js node_modules/

clean:
    rm *.zip
</code></pre>

<p>It's possible to have several "rules" to make a target in your file. Here, we have two targets: <code>lambda.zip</code> and <code>clean</code>. Simply running <code>make</code> – without params – from the command line will build the ZIP package. However running <code>make clean</code> will just remove all the ZIP files in the directory.</p>

<p>Our <code>lambda.zip</code> target depends on <code>clean</code> to run. But <code>clean</code> depends on nothing. Multiple dependencies are also allowed, if needed. If that's the case, separate them using spaces.</p>

<p>Below the target and its dependencies, there are the commands used to build the target. They must be indented using a <strong>tab</strong>. The <code>$@</code> is a reference to the target name.</p>

<h1 id="goingfurther">Going further</h1>

<p>We have a third target to test the app. It runs the <code>test</code> command declared in the <code>package.json</code> file.</p>

<pre><code>test:
    rm -rf node_modules/
    npm install
    npm test
</code></pre>

<p>Notice the difference in the dependencies install? Here we add all packages, not just the non-dev. That's because we have some libraries that are used for testing purposes.</p>

<p>Since we removed the <code>node_modules</code> directory in both <code>lambda.zip</code> and <code>test</code> targets, we could move it to a separated target and add it as a dependency. We ended up not doing that because it's a single liner and we don't use it alone. In contrast with <code>clean</code>, which is occasionally used with <code>make clean</code>.</p>

<h1 id="conclusion">Conclusion</h1>

<p>This post demonstrates a very simple way to use Make in your development workflow. Its powerful, yet flexible and there are people using it to build far more complex recipes.</p>

<p>If you want to dig deeper and learn more about Make and <code>Makefile</code> structure, there are lots of resources on the web. Though, you'll quickly find articles are about compiling C/C++ programs. This <a href="https://www.digitalocean.com/community/tutorials/how-to-use-makefiles-to-automate-repetitive-tasks-on-an-ubuntu-vps">Digital Ocean article</a> is a good starting place to learn how Make works and how it can be used to automate tasks. The <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html">man page</a> is also handy, especially after you have some experience.</p>

<p>Thanks for reading! If you have any comments or questions please leave them below.</p>]]></content:encoded></item><item><title><![CDATA[Manipulating uploaded files in Laravel]]></title><description><![CDATA[<p>We recently ran into a situation where the business logic of a project dictated that we can not have duplicate file contents. Regardless the naming convention, the <strong>contents</strong> of each file needed to remain unique. In this scenario, we were storing all types of uploaded files in a single directory.</p>]]></description><link>https://blog.kettle.io/manipulating-uploaded-files-laravel/</link><guid isPermaLink="false">a4908324-f241-4f94-9d42-d6ad7f6f34ee</guid><dc:creator><![CDATA[Gustavo Straube]]></dc:creator><pubDate>Tue, 14 Mar 2017 16:36:00 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2017/03/20bbee98-e64b-4151-bcbf-b5ad6563dbce.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.kettle.io/content/images/2017/03/20bbee98-e64b-4151-bcbf-b5ad6563dbce.jpg" alt="Manipulating uploaded files in Laravel"><p>We recently ran into a situation where the business logic of a project dictated that we can not have duplicate file contents. Regardless the naming convention, the <strong>contents</strong> of each file needed to remain unique. In this scenario, we were storing all types of uploaded files in a single directory.</p>

<p>To prevent content duplication, we needed to compare the newly uploaded file with files already in the destination directory.</p>

<p>Unfortunately, the Laravel documentation is not clear about the uploaded file class. Digging into the Laravel source code, you may find that instances returned by the <code>file()</code> method (from the request) are inherited from <code>SplFileInfo</code>. This means it is possible to manipulate the uploaded file with little hassle. Better yet, we can do this before storing the file.</p>

<p>You may find the evidence of the <code>SplFileInfo</code> class in <a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/File/File.php"><code>File</code></a>. It extends that class:</p>

<pre><code>class File extends \SplFileInfo  
{
</code></pre>

<p><br>
This reference to Symfony code may look odd if you are not familiar with the Laravel architecture, however Laravel uses lots of Symfony's components to form it's foundation.</p>

<p>Lets dive in and see how this class can be leveraged in our apps.</p>

<hr>

<h2 id="handleupload">Handle upload</h2>

<p>A basic file upload action may get the file instance from the request, check if an actual file was uploaded and finally store it. That may look something like this:</p>

<pre><code class="language-php">&lt;?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;  
use Symfony\Component\HttpFoundation\Response;

class FileController extends Controller  
{

    /**
     * Handle the file upload.
     *
     * @param  Request $request The request instance.
     * @return Response A response instance.
     */
    public function upload(Request $request)
    {

        /*
         * The form field was named "file".
         */
        $file = $request-&gt;file('file');

        if (empty($file)) {
            abort(400, 'No file was uploaded.');
        }

        $path = $file-&gt;store('uploads');

        // Do whatever you have to with the file.

    }
}
</code></pre>

<p><br></p>

<h2 id="readandcomparefilechunks">Read and compare file chunks</h2>

<p>Using the aforementioned file instance, we may write a function to compare the file with another <code>SpfFileInfo</code> instance. To speed things up, we don't have to compare the entire file. Its possible to read a small chunk of same size from each file and check the differences between them. As soon as a difference is found, the method returns.</p>

<pre><code class="language-php">/**
 * Compare the contents of two files to check if they have some difference.
 *
 * It does not check what exactly is different between files. This way, as 
 * soon as a difference is found, the function stops reading the files.
 *
 * @param  SplFileInfo $a The first file to compare.
 * @param  SplFileInfo $b The second file to compare.
 * @return bool Indicates if the files have differences between them.
 */
private function fileDiff($a, $b)  
{
    $diff = false;
    $fa = $a-&gt;openFile();
    $fb = $b-&gt;openFile();

    /*
     * Read the same amount from each file. Breaks the loop as soon as a 
     * difference is found.
     */
    while (!$fa-&gt;eof() &amp;&amp; !$fb-&gt;eof()) {
        if ($fa-&gt;fread(4096) !== $fb-&gt;fread(4096)) {
            $diff = true;
            break;
        }
    }

    /*
     * Just one of the files ended. This is unlikely to happen, though. 
     * Since we already checked before if the files have the same size.
     */
    if ($fa-&gt;eof() !== $fb-&gt;eof()) {
        $diff = true;
    }

    /*
     * Closing handlers.
     */
    $fa = null;
    $fb = null;

    return $diff;
}
</code></pre>

<p><br></p>

<h2 id="whataboutperformance">What about performance?</h2>

<p>Our function above is a good way of comparing two files contents. However, opening, reading and comparing the contents of <em>every</em> file in our uploads directory will be far too resource consuming (time, I/O, processing). We can significantly reduce the performance overhead by comparing the file sizes first, and only checking the content difference of matching size files. Here is what that would look like:</p>

<pre><code class="language-php">/**
 * Check if the given file was already uploaded.
 *
 * It loops through all files in the uploads directory, looking for anyone that 
 * could be equal to the currently uploaded file.
 *
 * @param  SplFileInfo $file The file to check.
 * @return bool Indicates if the file was already upload.
 */
private function isAlreadyUploaded($file)  
{
    $size = $file-&gt;getSize();

    /*
     * The directory where the files are stored.
     */
    $path = storage_path('app/uploads/');

    if (!is_dir($path)) {
        return false;
    }

    $files = scandir($path);
    foreach ($files as $f) {
        $filePath = $path . $f;
        if (!is_file($filePath)) {
            continue;
        }

        /*
         * If both files have the same size, check their contents.
         */
        if (filesize($filePath) === $size) {

            /*
             * Check if there are differences using the function we wrote above.
             */
            $diff = $this-&gt;fileDiff(new \SplFileInfo($filePath), $file);

            /*
             * Return the files are not different, meaning equal, that is 
             * already uploaded.
             */
            return !$diff;
        }
    }
    return false;
}
</code></pre>

<p><br></p>

<h2 id="handleandstorefile">Handle and store file</h2>

<p>Finally, we can call the last method from the upload action. Remember to only store the file after checking if it was previously uploaded.</p>

<pre><code class="language-php">/**
 * Handle the file upload.
 *
 * @param  Request $request The request instance.
 * @return Response A response instance.
 */
public function upload(Request $request)  
{

    /*
     * The form field was named "file".
     */
    $file = $request-&gt;file('file');

    if (empty($file)) {
        abort(400, 'No file was uploaded.');
    }

    /*
     * There is a file equal to the currently uploaded one in the uploads dir?
     */
    if ($this-&gt;isAlreadyUploaded($file)) {
        abort(400, 'This file was already imported.');
    }

    /*
     * Only stores the file after successfully checking if it is not at the 
     * destination already.
     */
    $path = $file-&gt;store('uploads');

    // Do whatever you have to with the file.

}
</code></pre>

<p><br></p>

<hr>

<h1 id="conclusion">Conclusion</h1>

<p>This is just one way to take advantage of the file roots to manipulate it. There are probably lots of other use cases where you may leverage this.</p>

<p>Also, its important to point out that this is just a helper given by the framework. You can certainly take other approaches to achieve the same result. For instance, its possible to store the file to a temporary path and then run all the required checks. Or use other file-related functions from PHP to manipulate the uploaded file.</p>

<p>Thanks for reading! If you have any comments or questions please leave them below.</p>]]></content:encoded></item><item><title><![CDATA[Object Queries with Redis]]></title><description><![CDATA[<p>Traditionally, many developers have opted to use relational databases when dealing with complex relationships between objects. For those of you who are used to working with relational databases like MySQL, a NoSQL database like Redis may seems like a difficult transition. </p>

<p>While Redis is best suited for use cases like</p>]]></description><link>https://blog.kettle.io/object-queries-with-redis/</link><guid isPermaLink="false">69ca4ed1-dc46-4f3a-8981-919d1f3d03fd</guid><dc:creator><![CDATA[Gustavo Straube]]></dc:creator><pubDate>Tue, 26 Jul 2016 19:43:00 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2016/07/185e6d5cbb92fd9a41b864984034609f.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.kettle.io/content/images/2016/07/185e6d5cbb92fd9a41b864984034609f.jpg" alt="Object Queries with Redis"><p>Traditionally, many developers have opted to use relational databases when dealing with complex relationships between objects. For those of you who are used to working with relational databases like MySQL, a NoSQL database like Redis may seems like a difficult transition. </p>

<p>While Redis is best suited for use cases like cache, queues, and leaderboards - it is possible to use Redis in front of a MySQL database. Doing this can improve overall query performance, while still allowing you to execute complex queries. </p>

<p>Let's go ahead and dive deeper to see what can be achieved using Redis based queries.</p>

<hr>

<h1 id="storingobjectdata">Storing Object Data</h1>

<p>Unlike traditional (RDBMS) databases, Redis is a key-value store. But it's an advanced one. There are many ways to store the values beyond a simple key/value pair, like lists or hashes. <strong>The way you choose to initially store the value will affect what you can do with it later.</strong></p>

<p>The methods we've listed below is not intended to be comprehensive. It's intended to just be a starting point.</p>

<h2 id="setsadd">Set (SADD)</h2>

<p>Within Redis, a <strong>set</strong> is a list of values. It may be used when a value is shared by multiple objects. </p>

<p>To store a member in a set, use <code>SADD</code>:</p>

<pre><code>&gt; SADD key member
</code></pre>

<p>Multiple members can be stored in a single call. We can also store product categories using a set, since several products will be under the same category. </p>

<p><code>SADD</code> can be called this way:</p>

<pre><code>&gt; SADD product:category:1 5 10
</code></pre>

<p>With this command, products with an ID <code>5</code> and <code>10</code> will be stored under the key of category with an ID <code>1</code>. It may seem odd to use the value (category ID) as the key. However, as you'll see in a bit, this is the best approach.</p>

<h2 id="sortedsetzadd">Sorted Set (ZADD)</h2>

<p>If you plan to query a value using <strong>ranges</strong> or comparison conditions such as <strong>less than</strong> or <strong>greater than</strong>, your pick is the sorted set.</p>

<p>The command used to store sorted set members is <code>ZADD</code>:</p>

<pre><code>&gt; ZADD key score member
</code></pre>

<p>You may pass multiple score/member pairs, if you wish to.</p>

<p>Sorted set are great to store information like prices. For this situation, the command will look something like:</p>

<pre><code>&gt; ZADD product:price 49.99 1 54.90 2
</code></pre>

<p>We are storing the price (score) <code>49.90</code> for the product with ID <code>1</code>, and <code>54.90</code> for the product with ID <code>2</code>. Both are set under the <code>product:price</code> key.</p>

<h2 id="hashhsetandhmset">Hash (HSET and HMSET)</h2>

<p>When each entity has a different value for an attribute, but you still want to query it, hash is a good choice.</p>

<p>Call <code>HSET</code> to set a field using a value:</p>

<pre><code>&gt; HSET key field value
</code></pre>

<p><strong>Note:</strong> Unlike the <code>ZADD</code> and <code>SADD</code> commands, <code>HSET</code> doesn't allow you to store multiple members (field and value) in a single call. Fortunately you can use a seperate but related command achieve that: <code>HMSET</code>.</p>

<p>Say you would like to search for products by their SKU. Since each product has a unique SKU, you can use a hash to store them by doing this:</p>

<pre><code>&gt; HSET product:sku '1ZN820' 1
</code></pre>

<p>Doing that, you're storing the SKU <code>1ZN820</code> for the product with an ID <code>1</code> within <code>product:name</code> key.</p>

<hr>

<h1 id="queryingobjectdata">Querying Object Data</h1>

<p>For each storage type (set, sorted set and hash) there are specific commands to fetch the keys and values. That is why its important to choose your storage method carefully, as you will be limited by the query on the other end.</p>

<h2 id="queryingsetssmembers">Querying Sets (SMEMBERS)</h2>

<p>Starting with the <strong>set</strong> type and the example given above, if you want to retrieve all products in a specific category - let's use the category with ID <code>2</code> - you simply call:</p>

<pre><code>&gt; SMEMBERS product:category:2
</code></pre>

<p>That will return a list of product ID's. With those ID's you can retrieve the product's objects.</p>

<p>In our specific use case, the full objects were stored in MySQL and we used Redis to speed up querying. We were doing this by performing a <code>SELECT</code> query on MySQL:</p>

<p><code>WHERE products.id IN ( ... )</code>. </p>

<p>Ultimately, it's up to you to decide where to store the objects: in Redis or elsewhere. Each use case is different.</p>

<h2 id="queryingsortedsetszrangebyscore">Querying Sorted Sets (ZRANGEBYSCORE)</h2>

<p>Previously, we saw that <strong>sorted set</strong> is a good choice to store values we want to query as numeric values – by range or using comparisons. This is not the only use for sorted sets, but its the only one we'll cover.</p>

<p>If you want to retrieve all product with price greater or equal to 50, you may call:</p>

<pre><code>&gt; ZRANGEBYSCORE product:price 50 +INF
</code></pre>

<p>The command expects 3 arguments: the key, lower limit and upper limit. As you can see we're passing the positive infinite (<code>+INF</code>) as the third argument. The negative infinite (<code>-INF</code>) is also available if you need it.</p>

<p>A specific range, like 40-50, can be also be used:</p>

<pre><code>&gt; ZRANGEBYSCORE product:price 40 50
</code></pre>

<h2 id="queryinghasheshmgetandhscan">Querying Hashes (HMGET and HSCAN)</h2>

<p>Finally, to search within the strings stored under a <strong>hset</strong>, let's perform the following call:</p>

<pre><code>&gt; HMGET product:name 'Cool product'
</code></pre>

<p>This would return the product having that exact name. It's also possible to do a partial match, similar to SQL's <code>LIKE</code> operator:</p>

<pre><code>&gt; HSCAN product:name 0 MATCH *ol*
</code></pre>

<p>The <code>*</code> is a wildcard for any amount of any characters. The command above would match <code>cool</code>, <code>toll</code> and <code>pole</code>.</p>

<p>You probably noticed the <code>0</code> as second argument. That is the current cursor. All Redis' commands from the <code>SCAN</code> family are iterators based on a cursor. After each call, the server will return the cursor for the next iteration. You should use it in the next call. Keep calling the server until you get <code>0</code> in the cursor.</p>

<h2 id="usingluaforscaniteration">Using Lua for SCAN iteration</h2>

<p>There is no command in Redis to loop through an iterator. Fortunately, Redis supports scripting with <a href="https://www.lua.org/">Lua</a> and we can use a small script to achieve that:</p>

<pre><code class="language-shell">    local cursor = 0
    local fields = {}
    local ids = {}
    local key = 'product:name'
    local value = '*' .. ARGV[1] .. '*'

    repeat
        local result = redis.call('HSCAN', key, cursor, 'MATCH', value)
        cursor = tonumber(result[1])
        fields = result[2]
        for i, id in ipairs(fields) do
            if i % 2 == 0 then
                ids[#ids + 1] = id
                redis.call('SADD', KEYS[1], id)
            end
        end
    until cursor == 0
    return ids
</code></pre>

<p>The code above returns all products that match a given value. It also stores that same result in a set, so we can use it again later. </p>

<p>To parse and run the script, call:</p>

<pre><code>&gt; EVAL 'local cursor; [...]' 1 tmp:name cool
</code></pre>

<p><code>EVAL</code> expects a script as the first argument, then the number of keys we're going to pass to the script, followed by the list of keys, and finally the list of arguments. </p>

<p>In our case here we passed one key (<code>tmp:name</code>) and one argument (<code>cool</code>). Inside the script, the key is accessed with <code>KEYS[1]</code> and the argument is accessed using <code>ARGV[1]</code>.</p>

<hr>

<h1 id="puttingalltogether">Putting all together</h1>

<p>By now, you have seen how to store and query each type of data. It's really useful, but in some cases the querying rules are more complex. </p>

<p>Let's say you have to find all products whose name contains "cool" <strong>and</strong> are priced in 50.00 or more. One way to do this is to fetch ID's for each condition and intersect the results client-side. However, in our opinion there is a better way:</p>

<pre><code>&gt; ZUNIONSTORE tmp:price 1 product:price WEIGHTS 1
&gt; ZREMRANGEBYSCORE tmp:price -INF (50
&gt; EVAL 'local cursor; [...]' 1 tmp:name cool
&gt; ZINTERSTORE tmp:result tmp:price tmp:name
&gt; ZRANGE tmp:result 0 -1
</code></pre>

<p>Let's go through each call:</p>

<ol>
<li>We start by creating a temporary copy of the product:price key using <strong>ZUNIONSTORE</strong>.  </li>
<li>We remove all values lower than 50 from the temporary copy. The <code>(</code> before the number indicates that 50 must be kept in the set.  </li>
<li>Run the iterator script storing all matched ID's in a temporary key.  </li>
<li>Intersect all values in <code>tmp:price</code> and <code>tmp:name</code>, storing the result as another key.  </li>
<li>Finally, we get all the values from the previous intersection.</li>
</ol>

<p>The last call will give you a list of ID's that, as explained in the begin, can be used to retrieve full objects.</p>

<p>Getting all products whose name contains "Cool" <strong>or</strong> are priced in 50.00 or more, is as simple as replacing <strong>ZINTERSTORE</strong> with <strong>ZUNIONSTORE</strong> in the fourth call.</p>

<h1 id="conclusion">Conclusion</h1>

<p>It is possible to combine more unions (<strong>OR</strong>) and intersections (<strong>AND</strong>) to fulfill even more complex logic. However, keep in mind that when mixing those group operations, the order <strong>does</strong> matter.</p>

<p>To dive into further detail on each command, the Redis <a href="http://redis.io/commands">list of commands</a> is a great place to start.</p>]]></content:encoded></item><item><title><![CDATA[Apple Watch, using Cordova + Ionic (Part 1)]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1>

<p>We have used Cordova + Ionic in the past to quickly prototype mobile apps for clients. Its proved to be a valuable tool because it allows us to re-use existing HTML, CSS and JavaScript we may have from a web project and compile it directly to iOS, Android and other</p>]]></description><link>https://blog.kettle.io/apple-watch-using-cordova-ionic-part-1/</link><guid isPermaLink="false">64aee04a-e996-4c2a-8e86-ccc993b3d013</guid><dc:creator><![CDATA[Adan Archila]]></dc:creator><pubDate>Mon, 16 May 2016 15:00:00 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2016/05/apple-watch.png" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>

<img src="http://blog.kettle.io/content/images/2016/05/apple-watch.png" alt="Apple Watch, using Cordova + Ionic (Part 1)"><p>We have used Cordova + Ionic in the past to quickly prototype mobile apps for clients. Its proved to be a valuable tool because it allows us to re-use existing HTML, CSS and JavaScript we may have from a web project and compile it directly to iOS, Android and other native platforms. </p>

<p>With the release of the Apple Watch, we were curious to see if there was a way to quickly prototype apps for the watch, using <a href="http://cordova.apache.org/">Cordova</a>. It turns out you can, with the help of <a href="https://github.com/Telerik-Verified-Plugins/AppleWatch">Cordova Apple Watch</a> from Telerik.</p>

<p>This is part of a 2 part post series. Between our two posts, we are going to build a simple navigation app for the iPhone and Watch, which work harmoniously together. In this first post we are working on just the iPhone app, which will allow users to search for an address, which is validated via Google Maps and initialize direction data.</p>

<hr>

<h1 id="setupcordovaxcodeapplewatchplugin">Set up Cordova + Xcode + Apple Watch Plugin</h1>

<p>First, lets create a new Cordova project. Be sure to have <a href="http://ionicframework.com/getting-started/">Ionic CLI tools</a> installed on your machine. We will need to install the <code>xcode</code> package from npm - the plugin hook will need it to inject code into the Cordova project. </p>

<pre><code class="language-shell">$ ionic start locator blank
$ cd locator
$ npm install xcode
$ ionic platform rm ios
</code></pre>

<p><br></p>

<p>As of this post, the latest version available is Cordova iOS v4.1.0. However, the Apple Watch plugin from Telerik is not yet compatible with Cordova iOS 4+, so we will need to install Cordova iOS 3.9.2 to get it working. </p>

<p>Before installing the iOS platform, open <code>locator/config.xml</code> and add your app ID - mine is <strong>co.kettleio.demo.locator</strong>. Your config.xml should look something like this:</p>

<pre><code class="language-xml">&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;  
&lt;widget id="co.kettleio.demo.locator" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"&gt;  
  &lt;name&gt;locator&lt;/name&gt;
  &lt;description&gt;
        An Ionic Framework and Cordova project.
    &lt;/description&gt;
  &lt;author email="you@example.com" href="http://example.com.com/"&gt;
      Your Name Here
    &lt;/author&gt;
  &lt;content src="index.html"/&gt;
  &lt;access origin="*"/&gt;
  &lt;preference name="webviewbounce" value="false"/&gt;
  &lt;preference name="UIWebViewBounce" value="false"/&gt;
  &lt;preference name="DisallowOverscroll" value="true"/&gt;
  &lt;preference name="SplashScreenDelay" value="2000"/&gt;
  &lt;preference name="FadeSplashScreenDuration" value="2000"/&gt;
  &lt;preference name="android-minSdkVersion" value="16"/&gt;
  &lt;preference name="BackupWebStorage" value="none"/&gt;
  &lt;feature name="StatusBar"&gt;
    &lt;param name="ios-package" value="CDVStatusBar" onload="true"/&gt;
  &lt;/feature&gt;
&lt;/widget&gt;  
</code></pre>

<p><br></p>

<p>Next, lets add the iOS platform to the project by running the following command:</p>

<pre><code class="language-shell">$ ionic platform add ios@3.9.2
</code></pre>

<p><br></p>

<p>With most of the preliminary work out of the way, we can begin working directly on the Xcode project. Open up the Xcode project, which is located in <code>platforms/ios</code> and make the following updates:</p>

<ol>
<li>Go to File > New > Target > watchOS > Application > Watchkit App for watchOS 1  </li>
<li>Select Objective-C as the language.  </li>
<li>Check the boxes for Glance and Notifications  </li>
<li>Click on Finish and then click on Activate</li>
</ol>

<p>Now let's switch back to the terminal and install the Telerik plugin: </p>

<pre><code class="language-shell">$ ionic plugin add https://github.com/Telerik-Verified-Plugins/AppleWatch
</code></pre>

<p><br></p>

<p>If the plugin was installed correctly you will see an Apple Watch drawn with ASCII and a few other messages indicating header files were properly installed. </p>

<hr>

<h1 id="configurexcode">Configure Xcode</h1>

<p>There are a few more steps necessary to build the project correctly.</p>

<h3 id="bundleversion">Bundle Version</h3>

<p>Set <strong>CFBundleVersion</strong> (bundle version) and <strong>CFBundleShortVersionString</strong> (bundle versions string, short) of all targets to the same value. To do this, use XCode's search feature <code>COMMAND + SHIFT + F</code> and change all 3 .plist values. This value must match your config.xml file, so in this example I'm setting the version to <strong>0.0.1</strong>.</p>

<p><img src="https://blog.kettle.io/content/images/2016/05/xcode-1.png" alt="Apple Watch, using Cordova + Ionic (Part 1)" title=""><br></p>

<h3 id="registerappid">Register App ID</h3>

<p>Register the app ID in your <a href="https://developer.apple.com/account">Apple Developer Account</a>: Certificates, Identifiers &amp; Profiles > App ID's > New. </p>

<p>Ensure this app ID matches the one we set inside config.xml earlier. You will also need to select <strong>App Groups</strong> in the enabled services section at the bottom.</p>

<p><img src="https://blog.kettle.io/content/images/2016/03/Screen-Shot-2016-03-25-at-10-50-37-AM.png" alt="Apple Watch, using Cordova + Ionic (Part 1)" title=""><br></p>

<h3 id="registerappgroup">Register App Group</h3>

<p>We need to register an App Group in our Apple Developer Account. From the dashboard go to Certificates, Identifiers &amp; Profiles > Identifiers > App Groups > Add New.</p>

<p><img src="https://blog.kettle.io/content/images/2016/03/Screen-Shot-2016-03-25-at-10-43-38-AM.png" alt="Apple Watch, using Cordova + Ionic (Part 1)" title=""><br></p>

<h3 id="createassignprovisioningprofile">Create + Assign Provisioning Profile</h3>

<ol>
<li>Go to Provisioning Profiles > Development and create a new profile for <em>iOS App Development</em>.  </li>
<li>Download the new profile and open it in Xcode.  </li>
<li>Go to the targets (Capabilities tab) and add the newly created app group to your target.  </li>
<li>Navigate to the <code>Build settings</code> tab and search for <strong>Bitcode</strong>. We will disable it by toggling the option to NO.  </li>
<li>Repeat steps 3-4 for all three targets:</li>
</ol>

<p><img src="https://blog.kettle.io/content/images/2016/05/provisioning.png" alt="Apple Watch, using Cordova + Ionic (Part 1)" title=""><br></p>

<h3 id="noterelmmwormhole">Note re: -lmmwormhole</h3>

<p>Some users have experienced this error:  </p>

<pre><code class="language-shell">ld: library not found for -lmmwormhole  
</code></pre>

<p>You can fix this by searching the Frameworks directory within Xcode for "libmmwormhole.a". There will be an option for <strong>Target Membership</strong> on the right sidebar of Xcode.</p>

<p>Deselect both targets, select them again, clean up the project ( Product > Clean) and then build the project again. This has seemingly fixed the linking issue.</p>

<hr>

<h1 id="createroutescontrollersviews">Create Routes, Controllers &amp; Views</h1>

<p>Now that we have a baseline up and running, lets recap the project goals:</p>

<ol>
<li>Create a view that will allow us to search for a valid location within our iOS app.  </li>
<li>Create a view that will show us the compass and destination data. This data/view will eventually be passed to the watch. </li>
</ol>

<p>This means we need to create two distinct views within our app: map and compass. Before we start building them, we are going to install 2 plugins. They will help us quickly build out the compass functionality: </p>

<pre><code class="language-shell">$ ionic plugin add cordova-plugin-device-orientation
$ ionic plugin add cordova-plugin-geolocation
</code></pre>

<p><br></p>

<hr>

<h2 id="setupthemap">Setup the Map</h2>

<p>We will start by creating a route and controller for the map. Open up your <code>www/js/app.js</code> file and add the following route:</p>

<pre><code class="language-javascript">.config(function($stateProvider, $urlRouterProvider) {

  $urlRouterProvider.otherwise('/')

  $stateProvider
  .state('index', {
    url: '/',
    templateUrl: 'map.html',
    controller: 'mapCtrl'
  })

})
</code></pre>

<p><br></p>

<p>Next, with the help of the Google Maps API, we are going to build the controller for our map view. The code we are going to modify can be found on <a href="https://developers.google.com/maps/documentation/javascript/examples/places-searchbox">Google's developer site</a>.</p>

<p>With a few tweaks, our map view controller will look like <strong><a href="https://gist.github.com/kettleio/b3c04198e9ca4102119d553db1dc0e6e">this gist</a></strong>. This code should go <em>after</em> your routes.</p>

<p>Some important notes about this block of code:</p>

<ol>
<li>The controller starts with <code>$scope.ifValidAddress = false</code> - this will allow us to keep the compass hidden, until we find a valid location on the map.  </li>
<li>The <code>$scope.disableTap</code> function is responsible for the Google Maps autocomplete.  </li>
<li>We created a Factory to save the search location. This will allow us to share the location information between views.</li>
</ol>

<h2 id="mapview">Map View</h2>

<p>The map view will simply have a fullscreen Google Map with a text input for location searching. We will connect the search to the <a href="https://developers.google.com/places/">Google Places API</a> for suggestions. Open the <code>index.html</code> file and include the Google Maps API &amp; Google Places libraries:</p>

<pre><code class="language-html">&lt;script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&amp;libraries=places" async defer&gt;&lt;/script&gt;  
</code></pre>

<p>Note, you will need to add your own API Key from the <a href="https://developers.google.com/maps/documentation/javascript/">Google Maps API</a>.</p>

<p>You will also need to update the <code>&lt;body&gt;</code> of your index.html file so it looks like this:</p>

<pre><code class="language-html">&lt;body ng-app="starter"&gt;

 &lt;ion-nav-bar class="bar-positive"&gt;
   &lt;ion-nav-back-button&gt;
   &lt;/ion-nav-back-button&gt;
 &lt;/ion-nav-bar&gt;
 &lt;ion-nav-view&gt;&lt;/ion-nav-view&gt;

&lt;/body&gt;  
</code></pre>

<p><br></p>

<p>Next, we are going to create a new file in the www directory called <code>map.html</code> and add our map view to it. The view will look like this:</p>

<pre><code class="language-html">&lt;ion-view view-title="Map"&gt;

   &lt;ion-nav-buttons side="right"&gt;
      &lt;button class="button icon-right ion-compass button-clear" ng-click="openCompass()" ng-show="ifValidAddress"&gt;&lt;/button&gt;
   &lt;/ion-nav-buttons&gt;
    &lt;ion-content scroll="false" &gt;

      &lt;input id="search-place" class="controls" type="text" placeholder="Search Address" ng-focus="disableTap()"&gt;
      &lt;div id="map"&gt;&lt;/div&gt;

    &lt;/ion-content&gt;

&lt;/ion-view&gt;  
</code></pre>

<p><br></p>

<p>This view accomplishes a few things for us:</p>

<ol>
<li>We are going to conditionally show the compass button if a valid location is found. We are using the <code>ng-show="ifValidAddress"</code> function for this.  </li>
<li>We added an input with <code>id="search-place"</code>. We'll use this data input to query the Google Places library.  </li>
<li>We added a div <code>id="map"</code> to insert the Google map.</li>
</ol>

<h2 id="mapstyles">Map Styles</h2>

<p>Now lets make it sexy with some CSS. Place the following code inside <code>www/css/style.css</code>:</p>

<pre><code class="language-css">#map {
    height: 100%;
}

.controls {
    margin-top: 10px;
    border: 1px solid transparent;
    border-radius: 2px 0 0 2px;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    height: 32px;
    outline: none;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

#search-place {
    background-color: #fff;
    font-family: Roboto;
    font-size: 15px;
    font-weight: 300;
    margin-left: 12px;
    padding: 0 11px 0 13px;
    text-overflow: ellipsis;
    width: 200px;
}

#search-place:focus {
    border-color: #4d90fe;
}

#type-selector {
    color: #fff;
    background-color: #4d90fe;
    padding: 5px 11px 0px 11px;
}

#type-selector label {
    font-size: 13px;
    font-weight: 300;
}
</code></pre>

<p><br></p>

<h2 id="testit">Test It</h2>

<p>At this point, you should be able to preview the app in your browser by running <strong>ionic server -lab</strong>. If the view is rending correctly and we are integrated with the Google Places API, you should see a map and search box:</p>

<p><img src="https://blog.kettle.io/content/images/2016/05/maps-demo.png" alt="Apple Watch, using Cordova + Ionic (Part 1)" title=""><br></p>

<hr>

<h2 id="setupthecompass">Setup the Compass</h2>

<p>Our final step is to create the compass view, which will show us all the navigation details. We are going to include the following details:</p>

<ol>
<li>Distance to destination (in meters)  </li>
<li>Bearing to destination (in degrees)  </li>
<li>Current heading  </li>
<li>Different between current heading and destination bearing (in degrees)  </li>
<li>Render a compass arrow based on the difference between the current heading and the destination bearing</li>
</ol>

<h3 id="addroute">Add Route</h3>

<p>Open the <code>app.js</code> file and add a route for your compass:</p>

<pre><code class="language-javascript">  .state('compass', {
    url: '/compass',
    templateUrl: 'compass.html',
    controller: 'compassCtrl'
  });
</code></pre>

<p><br></p>

<h3 id="createview">Create View</h3>

<p>Create a new file <code>compass.html</code> and add the following:</p>

<pre><code class="language-html">&lt;ion-view view-title="Compass"&gt;

  &lt;ion-content&gt;

    &lt;div class="list" id="results"&gt;
      &lt;div class="item item-divider"&gt;
        Location Details
      &lt;/div&gt;

      &lt;div class="item"&gt;
        Distance to destination
        &lt;span class="item-note"&gt;
          {{ distance }} meters
        &lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="item"&gt;
        Bearing to destination
        &lt;span class="item-note"&gt;
          {{ bearing }} degrees
        &lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="item"&gt;
        Current heading
        &lt;span class="item-note"&gt;
          {{heading}} 
        &lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="item"&gt;
        Difference in heading and bearing:
        &lt;span class="item-note"&gt;
          {{difference}} degrees
        &lt;/span&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;div class="item item-divider"&gt;
        Compass
      &lt;/div&gt;
      &lt;div class="item item-text-wrap arrow-container"&gt;
        &lt;div id="arrow" style="{{ animateRotation }}"&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

  &lt;/ion-content&gt;

&lt;/ion-view&gt;  
</code></pre>

<p><br></p>

<h3 id="updateindexhtml">Update index.html</h3>

<p>We are going to include a library by <a href="https://gist.github.com/kettleio/103fedc13685dfe9567aebcbcb55f16b">Chris Veness</a> to help manipulate the coordinates. Add this file and include it inside your index.html:</p>

<pre><code class="language-html">&lt;script type="text/javascript" src="js/latlon.js"&gt;&lt;/script&gt;  
</code></pre>

<p><br></p>

<h3 id="createcontroller">Create Controller</h3>

<p>With a view created, we must setup the controller which will look something like <strong><a href="https://gist.github.com/kettleio/5b74418c5a6f149ccbc7fcacc1980b8f">this gist</a></strong>.</p>

<hr>

<h1 id="conclusion">Conclusion</h1>

<p>At this point, you should be able to search for an address on your phone. Once a valid destination is found, you can tap the compass icon in the top right corner and watch the data update in real-time.</p>

<p>As we mentioned in the beginning, this is part one of our two part series. We will be posting a follow up in the coming weeks that outlines the Watch functionality.</p>

<p>If you'd like to view the entire code it is available on our <a href="https://github.com/kettleio/Apple-Watch-using-Cordova-Ionic">GitHub</a>. As always, comments are welcomed - please let us know if you found this helpful or have any questions!</p>]]></content:encoded></item><item><title><![CDATA[Event Driven API Cache]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1>

<p>Quite often we, as developers, cache resources in memory to improve app performance and reduce server load. By storing frequently accessed data in memory you avoid using CPU cycles to fetch a fixed set of data from your database. </p>

<p>Traditionally the cache concept has been limited to static data</p>]]></description><link>https://blog.kettle.io/event-driven-api-cache/</link><guid isPermaLink="false">9c08e6b3-4f52-44f5-94ca-25ad24a814b9</guid><dc:creator><![CDATA[Drew Witmer]]></dc:creator><pubDate>Fri, 15 Jan 2016 16:52:15 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2016/01/cD8Yjk6.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>

<img src="http://blog.kettle.io/content/images/2016/01/cD8Yjk6.jpg" alt="Event Driven API Cache"><p>Quite often we, as developers, cache resources in memory to improve app performance and reduce server load. By storing frequently accessed data in memory you avoid using CPU cycles to fetch a fixed set of data from your database. </p>

<p>Traditionally the cache concept has been limited to static data or data that has a long lifespan. What about API's that serve up frequently changing data? Many times this data is not truly "dynamic", but rather constantly changing. It's possible to cache these type of requests using an event driven architecture.</p>

<h2 id="eventdrivenscenario">Event Driven Scenario</h2>

<p>The concept is simple - every time a data change occurs an event is triggered. This event forces your cache to flush the old data and insert the new data. </p>

<p>Lets use the example of an eCommerce site with inventory data that contains product SKU's, price and number of units available. This data is cached so various services, like the website and iOS app, can pull product inventory levels without putting a tremendous load on the server.</p>

<p>Every time a new unit is sold or additional stock is added, the cache for that product must be updated. In this example, we have made the assumption that you are using a traditional database (MySQL or Postgres) with a cache layer placed on top. It is critically important to flush and insert the new data as quickly as possible to avoid any kind of read errors on inbound requests. Given the requirement of a quick flush and insert, what caching software is the best choice?</p>

<h2 id="redisormemcached">Redis or Memcached</h2>

<p>When it comes to in-memory caching there are two major players: <a href="http://redis.io/">Redis</a> and <a href="http://memcached.org/">Memcached</a>. Both are key-value storage based on NoSQL architecture. </p>

<p>Our simple experiment is not intended to represent all use cases, but rather provide some kind of baseline. Which software will not only be able to flush data quickly, but also re-populate it quickly?  </p>

<p>To compare the two we generated a sample data set with 500,000 records of SKU's, prices and units available. We inserted the entire data set into the cache, then flushed it. We ran this test 5 times and compiled the results below:  </p>

<p><strong>Redis (500,000 records)</strong></p>

<pre><code class="language-shell">Insert:  
        Max: 24196 ms
        Min: 23817 ms
        Avg: 24014 ms
Flush:  
        Max: 177 ms
        Min: 175 ms
        Avg: 176 ms
</code></pre>

<p><br></p>

<p><strong>Memcached (500,000 records)</strong></p>

<pre><code class="language-shell">Insert:  
        Max: 36862 ms
        Min: 36041 ms
        Avg: 36442 ms
Flush:  
        Max: 1 ms
        Min: 0 ms
        Avg: 0 ms
</code></pre>

<p><br></p>

<p>We expected Redis to win outright on both tests. However, the results reveal that Memcached has near instant flush characteristics. The insert performance of Redis was significantly better than Memcached, doing it nearly 35% quicker. With a larger data set, it's likely this margin would grow further.</p>

<p>This analysis does not account for the actual performance of the cache when serving requests. Generally Redis is regarded as having better performance and more robust caching due to a more advanced memory management algorithm. This experiment was simply intended to benchmark the insert/flush speed of each software.</p>

<p>Please leave a comment below if you have any questions!</p>]]></content:encoded></item><item><title><![CDATA[Hyper Fast API Using Elixir & Phoenix]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1>

<p>Just recently we've begun running tests with a new language called <a href="http://elixir-lang.org/">Elixir</a> and we are very excited about it for a few reasons. The language is built on top of the <a href="http://www.erlang.org/">Erlang VM</a> &amp; Open Telecom Platform (OTP), which is a highly proven network language that is used extensively</p>]]></description><link>https://blog.kettle.io/network-api-using-elixir-phoenix-and-mysql/</link><guid isPermaLink="false">e3fba6be-0d6d-4803-90f1-4a9477ae3317</guid><dc:creator><![CDATA[Drew Witmer]]></dc:creator><pubDate>Thu, 01 Oct 2015 16:28:00 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/09/elixir-nodes.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>

<img src="http://blog.kettle.io/content/images/2015/09/elixir-nodes.jpg" alt="Hyper Fast API Using Elixir & Phoenix"><p>Just recently we've begun running tests with a new language called <a href="http://elixir-lang.org/">Elixir</a> and we are very excited about it for a few reasons. The language is built on top of the <a href="http://www.erlang.org/">Erlang VM</a> &amp; Open Telecom Platform (OTP), which is a highly proven network language that is used extensively in telecommunications. It also forms the foundation of popular apps like Facebook Chat and WhatsApp.</p>

<p>So why are we excited about this language here at Kettle? We see a few high level benefits that it brings to the web:</p>

<p><strong>Concurrency:</strong> Elixir is designed around what they call a shared-nothing actor model, which allows it to efficiently take advantage of every available CPU core.<br>
<strong>Hot Code Updates:</strong> rather than immediately killing pending requests during code updates, Elixir will gracefully handle these processes before it updates the code.<br>
<strong>Fault-Tolerant:</strong> Elixir has built-in supervisors that restart parts of your program by reverting to a state that was known to be working.</p>

<h2 id="introducingphoenix">Introducing Phoenix</h2>

<p>As you can see, Elixir is a great choice when you need an extremely reliable and fast network application. There is a fantastic framework designed on top of Elixir called <a href="http://www.phoenixframework.org/">Phoenix</a>. It ships with many of the essential tools needed for building a web application: </p>

<ul>
<li>Familiar MVC structure making it easy and pleasant to work with</li>
<li>Database drivers via <a href="http://www.phoenixframework.org/docs/ecto-models">Ecto</a> </li>
<li>HTTP server via Cowboy</li>
<li>Module for filtering requests and responses via <a href="http://www.phoenixframework.org/docs/understanding-plug">Plug</a></li>
<li>Various tools for package management (hex) and unit testing (ex_unit)<br><br></li>
</ul>

<hr>

<h1 id="buildingascoringapi">Building a Scoring API</h1>

<p>Today we want to give Elixir a try and build a simple application with it. Our goal is to build an API that streams player scoring data, to a leaderboard, in real-time. In this example we are going to use MySQL, but if you're looking for something über fast, we recommend using MongoDB, which also has a native database driver included in Phoenix. </p>

<p>For this example, we will be using Phoenix V1.0.3.</p>

<h3 id="installphoenix">Install Phoenix</h3>

<p>There is an awesome <a href="http://www.phoenixframework.org/docs/installation">getting started guide</a> on the Phoenix website and we recommend following that. Here is a quick rundown of what you need to do. Make sure you have <a href="http://brew.sh/">Homebrew</a> on Mac installed first. Then install the prerequisite software:</p>

<pre><code class="language-ruby">$ brew install elixir
$ brew install erlang
$ brew install node
$ mix local.hex
</code></pre>

<p><br></p>

<p>After that, you can begin to install the phoenix framework:  </p>

<pre><code class="language-ruby">$ mix archive.install https://github.com/phoenixframework/phoenix/releases/download/v1.0.3/phoenix_new-1.0.3.ez
$ mix phoenix.new kettle_phoenix --database mysql 
## Note the database flag which defines MySQL as our DB driver
$ cd kettle_phoenix
$ mix ecto.create
$ mix phoenix.server
</code></pre>

<p><br></p>

<p>You should now see the Phoenix welcome screen at <a href="http://localhost:4000">http://localhost:4000</a>.</p>

<h3 id="createapiresources">Create API Resources</h3>

<p>Traditionally you would have to go through the process of creating a model, view and controller for your API to render. However, in Elixir there is a simple command to automate this process. It's called <a href="http://hexdocs.pm/phoenix/Mix.Tasks.Phoenix.Gen.Json.html">Mix.Tasks.Phoenix.Gen.Json</a> and it will automatically create the following resources for you:</p>

<ul>
<li>model in web/models</li>
<li>view in web/views</li>
<li>controller in web/controllers</li>
<li>migration file for the repository</li>
<li>test files for generated model and controller</li>
</ul>

<p>Let's go ahead and run this command to create the necessary resources to render our player names and their scores in a JSON file:</p>

<pre><code class="language-ruby">$ mix phoenix.gen.json Score scores player:string score:integer
</code></pre>

<p><br></p>

<h3 id="addroutes">Add Routes</h3>

<p>The terminal output from this command will return a new resource for the API scope, which belongs in <code>web/router.ex</code>. If you modified the data structure in the command above you will have a different output, however for this project we'll update our file to look like this:</p>

<pre><code class="language-ruby">defmodule KettlePhoenix.Router do  
  use KettlePhoenix.Web, :router

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/api", KettlePhoenix do
    pipe_through :api

    resources "/scores", ScoreController, except: [:new, :edit]
  end 

end  
</code></pre>

<p><br></p>

<h3 id="connectdatabase">Connect Database</h3>

<p>Next, we need to update the database connection details in <strong>config/dev.exs</strong>. </p>

<p>Then you can run the following commands to run the pending migrations:</p>

<pre><code class="language-shell">$ mix ecto.migrate
</code></pre>

<p><br></p>

<p>At this point we should verify the database has been updated. If everything looks good we can seed some data into the database.</p>

<p>Go ahead and start up the Elixir server:</p>

<pre><code class="language-shell">$ mix phoenix.server
</code></pre>

<p><br></p>

<p>We should see the endpoint serving up all player data at: <a href="http://localhost:4000/api/scores">http://localhost:4000/api/scores</a>. If you'd like to insert data you can do that via a simple cURL call:</p>

<pre><code class="language-shell">$ curl -X POST -H "Content-Type: application/json" -d '{ "score": { "player": "Jack Bauer", "score": "100" } }' http://localhost:4000/api/scores
</code></pre>

<p><br></p>

<hr>

<h1 id="conclusion">Conclusion</h1>

<p>While this was a quick and simple example, it should highlight how developer friendly Elixir is. With a relatively small amount of code we are able to build a very robust, scalable and fault-tolerant API. You could certainly add additional routes, with filters to sort and parse this data further.</p>

<p>We hope you enjoyed this article. Please feel free to leave comments below. The entire project is available on <a href="https://github.com/kettleio/Phoenix-Scoring-API">Kettle's GitHub</a>.</p>]]></content:encoded></item><item><title><![CDATA[Debugging cURL Requests In PHP]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1>

<p>cURL is a great library and tool. Quite often we'll use it to interact and fetch data from third-party API's. However, sometimes debugging requests made with cURL, specifically from a PHP application, can be tricky. </p>

<p>Let's say you have an integration with a third-party API and the service becomes</p>]]></description><link>https://blog.kettle.io/debugging-curl-requests-in-php/</link><guid isPermaLink="false">febd0bcc-5a4a-4e70-99be-a816c7249399</guid><dc:creator><![CDATA[Gustavo Straube]]></dc:creator><pubDate>Mon, 21 Sep 2015 22:05:48 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/09/20931666934_90cf7123ce_k.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>

<img src="http://blog.kettle.io/content/images/2015/09/20931666934_90cf7123ce_k.jpg" alt="Debugging cURL Requests In PHP"><p>cURL is a great library and tool. Quite often we'll use it to interact and fetch data from third-party API's. However, sometimes debugging requests made with cURL, specifically from a PHP application, can be tricky. </p>

<p>Let's say you have an integration with a third-party API and the service becomes unstable. Some requests respond as expected, while others do not. How can we determine where the code is failing? </p>

<h2 id="uselogsnotexceptions">Use Logs, Not Exceptions</h2>

<p>Just recently, we ran into a situation where one of our cURL integrations was failing. In production environments we capture and log all exceptions using an app called <a href="https://getsentry.com/">Sentry</a>. Unfortunately, in this particular situation, the exception output did not reveal very much about what was happening with our cURL requests. </p>

<p>To get detailed information we needed to save detailed information to a log file. This required a few additions and updates to our code.</p>

<h2 id="usingoutputbuffer">Using Output Buffer</h2>

<p>We start by turning on the <a href="http://php.net/manual/en/book.outcontrol.php">PHP output buffer (OB)</a> and strting the output stream. This allows us to write  verbose information from cURL to the output buffer. We must do this <strong>before</strong> starting the cURL handler.</p>

<pre><code class="language-php">ob_start();  
$out = fopen('php://output', 'w');
</code></pre>

<p><br>
Then we needed to turn on verbose output information and define the output stream.</p>

<pre><code class="language-php">$curl = curl_init();
curl_setopt($curl, CURLOPT_VERBOSE, true);  
curl_setopt($curl, CURLOPT_STDERR, $out);  
</code></pre>

<p><br>
After the <strong>curl_exec()</strong> call you can close the stream and fetch the information from the output buffer. To correctly capture all the information from cURL you must do it in this order - first close the stream and then get the contents.</p>

<pre><code class="language-php">fclose($out);  
$debug = ob_get_clean();
</code></pre>

<p><br>
Now the <strong>$debug</strong> variable will hold a string containing data like this:</p>

<pre><code class="language-text">* Hostname was NOT found in DNS cache
*   Trying 23.21.53.220...
* Connected to requestb.in (23.21.53.220) port 80 (#0)
&gt; POST /zn36z0zn HTTP/1.1
Host: requestb.in  
Accept: application/json  
Content-Length: 9  
Content-Type: application/x-www-form-urlencoded

* upload completely sent off: 9 out of 9 bytes
&lt; HTTP/1.1 200 OK  
&lt; Connection: keep-alive  
* Server gunicorn/19.3.0 is not blacklisted
&lt; Server: gunicorn/19.3.0  
&lt; Date: Fri, 18 Sep 2015 23:42:28 GMT  
&lt; Content-Type: text/html; charset=utf-8  
&lt; Content-Length: 2  
&lt; Sponsored-By: https://www.runscope.com  
&lt; Via: 1.1 vegur  
&lt;  
* Connection #0 to host requestb.in left intact
</code></pre>

<p><br>
Optionally, you can append the response body to the <strong>$debug</strong> variable. We did that to see what the service was returning when a unexpected error occurred.</p>

<p>We hope you found this article helpful. Please leave a comment below if you have any questions!</p>]]></content:encoded></item><item><title><![CDATA[Token Authentication Using Laravel + iOS - Part II]]></title><description><![CDATA[<h1 id="buildingahybridiosapp">Building a Hybrid iOS App</h1>

<p>This is a follow-up to our post on <a href="http://blog.kettle.io/token-authentication-using-laravel-ios/">Token Authentication Using Laravel + iOS</a>. In our previous post we covered the backend API and how to configure Laravel token authentication. In this post we will build a hybrid iOS app using <a href="https://cordova.apache.org/">Apache Cordova</a> along with the</p>]]></description><link>https://blog.kettle.io/hybrid-ios-app-and-token-authentication-with-laravel/</link><guid isPermaLink="false">63047c75-73f2-4798-87a2-9370a1893387</guid><dc:creator><![CDATA[Adan Archila]]></dc:creator><pubDate>Thu, 10 Sep 2015 22:32:00 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/09/8OknF9u.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="buildingahybridiosapp">Building a Hybrid iOS App</h1>

<img src="http://blog.kettle.io/content/images/2015/09/8OknF9u.jpg" alt="Token Authentication Using Laravel + iOS - Part II"><p>This is a follow-up to our post on <a href="http://blog.kettle.io/token-authentication-using-laravel-ios/">Token Authentication Using Laravel + iOS</a>. In our previous post we covered the backend API and how to configure Laravel token authentication. In this post we will build a hybrid iOS app using <a href="https://cordova.apache.org/">Apache Cordova</a> along with the <a href="https://onsen.io/">Onsen UI</a> framework.</p>

<p>Our goal was to build a simple iOS to-do app that would connect to our backend API using token authentication (via JSON). This post will show you how to set up Cordova, Onsen UI and create the necessary templates for our to-do app. Let's get started.<br><br></p>

<hr>

<h1 id="prerequisites">Prerequisites</h1>

<p>Before we start building the hybrid app we need to setup a base installation of Cordova + Onsen and configure our API server.</p>

<h2 id="1installcordovaonsen">1. Install Cordova + Onsen</h2>

<p>There is a <a href="https://onsen.io/guide/getting_started.html">fantastic guide</a> on Onsen's site that walks you through this process. In summary you'll need to do the following:</p>

<ol>
<li>Install <a href="https://nodejs.org/en/">NodeJS</a> and <a href="https://www.npmjs.com/">NPM</a> on your machine. We recommend using <a href="http://brew.sh/">Brew</a> for this by simply running <strong>brew install node</strong> and <strong>brew install npm</strong>.  </li>
<li>Run the command <strong>sudo npm install -g cordova</strong> to install the Cordova package globally.</li>
<li>Download the <a href="https://onsen.io/project-templates/gen/onsenui-master-detail.zip">master-detail</a> template from the Onsen site.</li>
<li>Navigate to the unzipped folder and run the command <strong>cordova platform add ios</strong> to add the iOS SDK to the folder.</li>
<li>Ensure you have Xcode Command Line Tools by running <strong>xcode-select --install</strong> and ios-sim by running <strong>sudo npm install -g ios-sim</strong>.</li>
<li>You can now run <strong>cordova emulate</strong> to open the simulator and preview your app at any time.</li>
</ol>

<h2 id="2enablecors">2. Enable CORS</h2>

<p>You need to enable CORS on your API server to allow remote access on the GET, POST and DELETE methods. There are different configuration requirements depending on the HTTP server your using. </p>

<p>Below are configurations for <u>wide open</u> CORS on Nginx and Apache. Use with caution and discretion. It's recommended that you understand what you are doing.</p>

<h3 id="nginx">Nginx</h3>

<p>Place this block of code inside your Nginx server block and then restart the Nginx service using <strong>service nginx restart</strong> on Ubuntu. You may optionally need to install the Nginx extras for support on the <code>more_set_headers</code>. You can do that by running this command on Ubuntu: <strong>apt-get install nginx-extras</strong>.</p>

<pre><code class="language-shell">more_set_headers 'Access-Control-Allow-Origin: $http_origin';  
more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, HEAD';  
more_set_headers 'Access-Control-Allow-Credentials: true';  
more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization';

location / {  
    if ($request_method = 'OPTIONS') {
        more_set_headers 'Access-Control-Allow-Origin: $http_origin';
        more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, HEAD';
        more_set_headers 'Access-Control-Max-Age: 1728000';
        more_set_headers 'Access-Control-Allow-Credentials: true';
        more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization';
        more_set_headers 'Content-Type: text/plain; charset=UTF-8';
        more_set_headers 'Content-Length: 0';
        return 204;
    }
    try_files $uri $uri/ /index.php?$query_string;
}
</code></pre>

<h3 id="apache">Apache</h3>

<p>On Apache it's a much easier. Simply add this line to your .htaccess file and restart Apache using <strong>service apache2 reload</strong> on Ubuntu.  </p>

<pre><code class="language-shell">Header set Access-Control-Allow-Origin "*"  
</code></pre>

<p><br></p>

<hr>

<h1 id="views">Views</h1>

<p>Now that we have a base app up and running we need to create the following views for our app:</p>

<ul>
<li>Login</li>
<li>Home</li>
<li>Add Todo</li>
</ul>

<p>Please note, all our views will live within the <code>www/index.html</code> file. </p>

<p>We want to clean this file up a little before starting. Lets remove the <code>&lt;style&gt;</code> block in the head and the entire <code>&lt;body&gt;</code> from the starter template. You'll be left with something like this:</p>

<pre><code class="language-html">&lt;!DOCTYPE html&gt;  
&lt;!-- CSP support mode (required for Windows Universal apps): https://docs.angularjs.org/api/ng/directive/ngCsp --&gt;  
&lt;html lang="en" ng-app="app" ng-csp&gt;  
&lt;head&gt;  
    &lt;meta charset="utf-8" /&gt;
    &lt;meta name="apple-mobile-web-app-capable" content="yes" /&gt;
    &lt;meta name="mobile-web-app-capable" content="yes" /&gt;

    &lt;!-- JS dependencies (order matters!) --&gt;
    &lt;script src="scripts/platformOverrides.js"&gt;&lt;/script&gt;
    &lt;script src="lib/angular/angular.js"&gt;&lt;/script&gt;
    &lt;script src="lib/onsen/js/onsenui.js"&gt;&lt;/script&gt;

    &lt;!-- CSS dependencies --&gt;
    &lt;link rel="stylesheet" href="lib/onsen/css/onsenui.css" /&gt;
    &lt;link rel="stylesheet" href="lib/onsen/css/onsen-css-components-blue-basic-theme.css" /&gt;

    &lt;!-- CSP support mode (required for Windows Universal apps) --&gt;
    &lt;link rel="stylesheet" href="lib/angular/angular-csp.css" /&gt;


    &lt;!-- --------------- App init --------------- --&gt;
    &lt;script src="js/app.js"&gt;&lt;/script&gt;

    &lt;title&gt;Onsen UI - Todo App&lt;/title&gt;

&lt;/head&gt;  
&lt;body&gt;  
    &lt;!-- Cordova reference --&gt;
    &lt;script src="cordova.js"&gt;&lt;/script&gt;
    &lt;script src="scripts/index.js"&gt;&lt;/script&gt;
    &lt;!-- --&gt;
&lt;/body&gt;  
&lt;/html&gt;  
</code></pre>

<p><br></p>

<h2 id="loginview">Login View</h2>

<p>The login view will contain the following elements:</p>

<ul>
<li>A basic form (email and password) with a submit button. </li>
<li>A modal with a loading message: <em>Please wait. Connecting...</em>. </li>
<li>A button in the toolbar with a loading icon, which shows when we are fetching data from the API. We enable this using the function <strong>ng-show="isFetching"</strong>.</li>
</ul>

<p>Each view will eventually have its own Angular controller. For this view we have attached a <strong>LoginController</strong> which will execute at the beginning via the <strong>ng-init="init()"</strong> function. You will see later in this post how we are going to run this function. </p>

<p>The login view, in conjunction with the controller, will check if we have a token stored in local storage and verify if this token is still valid. If the token is valid it will pass the user to the Home template where the user will see their todos. If the token is invalid it will show the user a login form.</p>

<p>Place this code directly below the cordova-reference in the body.</p>

<pre><code class="language-html">&lt;ons-navigator var="navi"&gt;  
    &lt;ons-page ng-controller="LoginController" ng-init="init()"&gt;
        &lt;ons-toolbar&gt;
            &lt;div class="center"&gt;Todo&lt;/div&gt;
            &lt;div class="right"&gt;
                &lt;ons-toolbar-button ng-show="isFetching"&gt;
                    &lt;ons-icon icon="ion-load-c" spin="true"&gt;
                &lt;/ons-toolbar-button&gt;
            &lt;/div&gt;
        &lt;/ons-toolbar&gt;

        &lt;div class="login-form" ng-hide="isLogged"&gt;

            &lt;input type="email" class="text-input--underbar" ng-model="email" placeholder="Email" &gt;
            &lt;input type="password" class="text-input--underbar" ng-model="password" placeholder="Password"&gt;                
            &lt;br&gt;&lt;br&gt;
            &lt;ons-button modifier="large" class="login-button" ng-click="login()"&gt;Log In&lt;/ons-button&gt;             

        &lt;/div&gt;

        &lt;ons-modal var="loginModal"&gt;
            &lt;ons-icon icon="ion-loading-c" spin="true"&gt;&lt;/ons-icon&gt;
            &lt;br&gt;&lt;br&gt;
            Please wait.&lt;br&gt;Connecting...
        &lt;/ons-modal&gt; 

    &lt;/ons-page&gt;        
&lt;/ons-navigator&gt;  
</code></pre>

<p><br></p>

<h2 id="homeview">Home View</h2>

<p>The home view will use the default Onsen UI list style to render the todos. In addition to listing the todo's we will include a few more UI features:</p>

<ul>
<li>A button to add todos.</li>
<li>A loading icon that shows while todos are being added.</li>
<li>A swipe to delete interaction. This is achieved by using the <code>&lt;ons-carousel&gt;</code> tag. This tag allows us to include 2 slides - one for the todo and another for the delete button.</li>
<li>A modal to indicate when a todo is being deleted. </li>
</ul>

<p>Add this block of code directly below your login view code.</p>

<pre><code class="language-languate-html">&lt;ons-template id="home.html"&gt;  
    &lt;ons-page ng-controller="HomeController" ng-init="init()"&gt;
        &lt;ons-toolbar&gt;
            &lt;div class="left"&gt;
                &lt;ons-toolbar-button ng-show="isFetching"&gt;
                    &lt;ons-icon icon="ion-load-c" spin="true"&gt;
                &lt;/ons-toolbar-button&gt;
            &lt;/div&gt;
            &lt;div class="center"&gt;Todo List&lt;/div&gt;
            &lt;div class="right"&gt;
                &lt;ons-toolbar-button ng-click="showAddTodo()"&gt;
                    &lt;ons-icon icon="ion-compose"&gt;
                &lt;/ons-toolbar-button&gt;
            &lt;/div&gt;
        &lt;/ons-toolbar&gt;

        &lt;ons-list modifier="todo-list chevron"&gt;
            &lt;ons-list-item class="item" ng-repeat="item in items"&gt;
                &lt;ons-carousel style="height: 44px; width: 100%" swipeable initial-index="0" auto-scroll&gt;
                    &lt;ons-carousel-item&gt;
                        &lt;ons-button modifier="large--quiet" class="todo-btn"&gt;{{item.title}}&lt;/ons-button&gt;
                    &lt;/ons-carousel-item&gt;
                    &lt;ons-carousel-item&gt;
                        &lt;ons-button modifier="large" class="delete-btn" ng-click="deleteTodo(item.id)"&gt;Delete&lt;/ons-button&gt;
                    &lt;/ons-carousel-item&gt;
                &lt;/ons-carousel&gt;
            &lt;/ons-list-item&gt;
        &lt;/ons-list&gt;

        &lt;ons-modal var="deleteModal"&gt;
            &lt;ons-icon icon="ion-loading-c" spin="true"&gt;&lt;/ons-icon&gt;
            &lt;br&gt;&lt;br&gt;
            Deleting Todo...
        &lt;/ons-modal&gt; 

    &lt;/ons-page&gt;

&lt;/ons-template&gt;
</code></pre>

<p><br></p>

<h2 id="addtodoview">Add Todo View</h2>

<p>This view contains a simple form and submit button for adding a new todo item.  It will also contain a modal to let the user know when a todo is being saved to the API. This view will work with the <strong>addTodoController</strong> controller to create new todo items.</p>

<p>Add this block of code directly below your home view code.</p>

<pre><code class="language-languate-html">&lt;ons-template id="add.html"&gt;  
    &lt;ons-page ng-controller="addTodoController"&gt;

        &lt;ons-toolbar&gt;
            &lt;div class="left"&gt;&lt;ons-back-button&gt;Back&lt;/ons-back-button&gt;&lt;/div&gt;
            &lt;div class="center"&gt;Add Todo&lt;/div&gt;
        &lt;/ons-toolbar&gt;

        &lt;ons-list modifier="inset" style="margin-top: 10px"&gt;
            &lt;ons-list-item&gt;
                &lt;input type="text" class="text-input text-input--transparent" ng-model="todo" placeholder="Task" style="width: 100%"&gt;
            &lt;/ons-list-item&gt;
        &lt;/ons-list&gt;

        &lt;div style="padding: 10px 9px"&gt;
            &lt;ons-button modifier="large" style="margin: 0 auto;" ng-click="submitTodo()"&gt;Add Todo&lt;/ons-button&gt;
        &lt;/div&gt;

        &lt;ons-modal var="todoModal"&gt;
            &lt;ons-icon icon="ion-loading-c" spin="true"&gt;&lt;/ons-icon&gt;
            &lt;br&gt;&lt;br&gt;
            Adding Todo...
        &lt;/ons-modal&gt; 

    &lt;/ons-page&gt;
&lt;/ons-template&gt;  
</code></pre>

<p><br></p>

<hr>

<h1 id="angularjscontrollers">AngularJS Controllers</h1>

<p>At this point you can run <strong>cordova emulate</strong> and you can preview the app. There isn't much to see, but if you did everything correctly up to this point you should see a simple screen with a "ToDo" title. </p>

<p>In order to bring the app to life we will need an AngularJS controller for each view. We will need to create the following controllers:</p>

<ul>
<li>LoginController</li>
<li>HomeController</li>
<li>addTodoController</li>
</ul>

<p>All controller related logic will go in the <code>www/js/app.js</code> file. Before starting, let's strip some of the default code so we end up with the following:</p>

<pre><code class="language-javascript">(function(){
  'use strict';
})();
</code></pre>

<p><br></p>

<p>Next, we need to define some variables that will help simplify the process for us. The <strong>api</strong> variable will be our API endpoint, and the <strong>Object.toparams</strong> function will convert parameters to JSON in our POST methods. Add this within the main function, after the <code>use strict</code> declaration. Be sure to update the <strong>api</strong> variable.</p>

<pre><code class="language-javascript">  var api = 'http://yourserver.com/api/';
  var module = angular.module('app', ['onsen']);

  Object.toparams = function ObjecttoParams(obj) {
    var p = [];
    for (var key in obj) {
      p.push(key + '=' + encodeURIComponent(obj[key]));
      console.log(obj[key]);
    }
    return p.join('&amp;');
  };
</code></pre>

<p><br></p>

<h2 id="logincontroller">LoginController</h2>

<p>Our login controller has two main functions: <code>init()</code> and <code>login()</code>. </p>

<p>The <code>init()</code> funtion will run on load and check if we have a key called <code>token</code> in local storage. If the token exists the controller will attempt to validate it by sending a GET request to the <code>validate_token</code> route. If the token is valid, it will redirect the user to the home view. If not, it show the login form. </p>

<p>The <code>login()</code> function will pass the email and password input values as a POST method to the <code>login</code> route. If the credentials are valid, the API will return a token which is stored in the local storage. The user will then be redirected to the home view. If the credentials are invalid, the controller will return an error and show the login form again.</p>

<p>Place this block of code below your <code>ObjecttoParams</code> function.</p>

<pre><code class="language-javascript">module.controller('LoginController', function($scope, $http) {

  $scope.isLogged = true;
  $scope.isFetching = false;
  $scope.email = '';
  $scope.password = '';

  $scope.init = function(){
    $scope.isFetching = true;

    if (window.localStorage.getItem("token") !== null ) {
      $http.get(api+'validate_token?token='+window.localStorage.getItem("token")).success(
        function(response) {
          console.log(response);
          if( typeof(response.status) !== "undefined"){
            $scope.isLogged = true;
            $scope.isFetching = false;
            $scope.navi.pushPage('home.html');
          } else {
            $scope.isLogged = false;
            $scope.isFetching = false;
          }
        }
      ).error(function(response){
        $scope.isFetching = false;
      });

    } else {    
      $scope.isLogged = false;
      $scope.isFetching = false;
    } 
  };

  $scope.login = function(){
    if($scope.email==='' || $scope.password===''){     
      ons.notification.alert({message: "You can't leave any fields empty"});
    } else {   
      loginModal.show();
      var data = {
        email: $scope.email,
        password: $scope.password
      };

      $http({
        url: api+'login',
        method: 'POST',
        data: Object.toparams(data),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      }).success(function (response) {
        console.log(response);
        if( typeof(response.token) !== "undefined"){
          window.localStorage.setItem("token", response.token);
          loginModal.hide();
          $scope.navi.pushPage('home.html');
        } else {
          loginModal.hide();
          ons.notification.alert({message: 'Your username/password was incorrect, please try again.'});
        }
        }).error(function(response){
          loginModal.hide();
          $scope.isFetching = false;
      });
    }
  };
});
</code></pre>

<p><br></p>

<h2 id="homecontroller">HomeController</h2>

<p>The home controller has 3 main functions: <code>init()</code>, <code>showAddTodo()</code> and <code>deleteTodo()</code>. </p>

<p>The <code>init()</code> function will run on load and send a GET request to the <code>todo</code> route (with the token from our local storage). The API will validate the token and respond with a JSON object containing all the todo items for the user. We will assign this list of todos to the <code>$scope.items</code> variable, and include it on the ng-repeat in the home view.</p>

<p>The <code>showAddTodo()</code> function redirects users to the add todo view.</p>

<p>The <code>deleteTodo()</code>, when triggered, will send a DELETE request to the selected Todo upon a successful response it will send you back to the home.html page and also restart the <code>init()</code> function so the app can grab the fresh list of Todos from the API. </p>

<p>We also included an event called <code>rootScope:refreshtodos</code> we are gonna make use of this one in the next controller, when I trigger this event in the next controller I will just refresh the list of Todos by running the <code>init()</code> function again. </p>

<p>Place this block of code below our LoginController.</p>

<pre><code class="language-javascript">module.controller('HomeController', function($scope, $http, $rootScope) {  
  $scope.isFetching = true;
  $scope.items = [];

  $scope.init = function(){

    $http.get(api+'todo?token='+window.localStorage.getItem("token")).success(
      function(response) {
        console.log(response);
        if( typeof(response.status) !== "undefined"){

          $scope.isFetching = false;
          $scope.items = response.todos;

        } else {
          ons.notification.alert({message: 'There was an error connecting to the API.'});
          $scope.isFetching = false;
        }
      }
    ).error(function(response){
      ons.notification.alert({message: 'There was an error connecting to the API.'});
      $scope.isFetching = false;
    });

  };

  $scope.showAddTodo = function(index) {
    $scope.navi.pushPage('add.html');
  };

  $scope.deleteTodo = function(id){
    deleteModal.show();

    $http({
      url: api+'todo/'+id+'?token='+window.localStorage.getItem("token"),
      method: 'DELETE',
      headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    }).success(function (response) {
      console.log(response);
      if( typeof(response.status) !== "undefined"){
        deleteModal.hide();
        $scope.init();
      } else {
        deleteModal.hide();
        ons.notification.alert({message: 'There was an error connecting to the API, please try again.'});
      }
    });
  };

  $rootScope.$on('rootScope:refreshtodos', function (event, data) {
    $scope.init();
  });

});
</code></pre>

<p><br></p>

<h2 id="addtodocontroller">addTodoController</h2>

<p>This controller has one function: <code>submitTodo()</code> which will send a POST request to the <code>todo</code> route. If we receive a successful response, the controller will broadcast the event to <code>rootScope:refreshtodos</code> so the home view can refresh the todo list. It will then redirect the user back to the home view.</p>

<p>Place this block of code below your HomeController.</p>

<pre><code class="language-javascript">module.controller('addTodoController', function($scope, $http, $rootScope) {

  $scope.isFetching = false;
  $scope.todo = '';

  $scope.submitTodo = function(){
    if($scope.todo===''){    
      ons.notification.alert({message: "You can't leave the field empty"});
    } else {

      todoModal.show();
      var data = {
        title: $scope.todo
      };

      $http({
        url: api+'todo?token='+window.localStorage.getItem("token"),
        method: 'POST',
        data: Object.toparams(data),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      }).success(function (response) {
        console.log(response);
        if( typeof(response.status) !== "undefined"){
          todoModal.hide();
          $rootScope.$broadcast('rootScope:refreshtodos', 'RefreshTodos');
          $scope.navi.popPage();
        } else {
          todoModal.hide();
          ons.notification.alert({message: 'There was an error connecting to the API, please try again.'});
        }
      });
    }
  };
});
</code></pre>

<p><br></p>

<hr>

<h1 id="conclusion">Conclusion</h1>

<p>You may now test the app by running <strong>cordova emulate</strong> from the root project folder. At this point feel free to customize the app styles or add additional features.</p>

<h2 id="distribution">Distribution</h2>

<p>Once everything is running you can prepare the app for distribution using three simple steps:</p>

<ol>
<li>Run the command <strong>cordova prepare</strong> to prepare the Xcode files.  </li>
<li>Open the <code>platforms/ios/Onsen UI Project.xcodeproj</code> file in Xcode.  </li>
<li>Generate an .ipa file by navigating to <em>Project -> Archive</em>.</li>
</ol>

<h2 id="repository">Repository</h2>

<p>You can download this project directly from our Github repo <a href="https://github.com/kettleio/hybrid-onsen-app">Hybrid Onsen App</a>.</p>

<p>Thanks for reading! If you have any comments or questions please leave them below.</p>]]></content:encoded></item><item><title><![CDATA[Token Authentication Using Laravel + iOS]]></title><description><![CDATA[<h1 id="introduction">Introduction</h1>

<p>Just recently we were tasked with developing a web + iOS app for a client. We wanted to leverage the speed &amp; simplicity of building for the web using <a href="http://laravel.com/">Laravel</a>, but utilize this same backend architecture for the iOS app. This meant we needed to create a RESTful API to</p>]]></description><link>https://blog.kettle.io/token-authentication-using-laravel-ios/</link><guid isPermaLink="false">e2e394df-5ea0-4f29-8ef9-3ac7cb0e5536</guid><dc:creator><![CDATA[Adan Archila]]></dc:creator><pubDate>Sun, 24 May 2015 20:16:04 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/06/DSC00028-2.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>

<img src="http://blog.kettle.io/content/images/2015/06/DSC00028-2.jpg" alt="Token Authentication Using Laravel + iOS"><p>Just recently we were tasked with developing a web + iOS app for a client. We wanted to leverage the speed &amp; simplicity of building for the web using <a href="http://laravel.com/">Laravel</a>, but utilize this same backend architecture for the iOS app. This meant we needed to create a RESTful API to interact with our iOS app. </p>

<p>As with most apps, this one required authentication. We decided to use tokens for our authentication module. This article is apart of a two part series designed to demonstrate how to build a basic API which will eventually interact with an iOS to-do app. It will then demonstrate how to connect the iOS app &amp; API using a token authentication system (via JSON). </p>

<p>This particular article will cover the API that runs behind the scenes. We will be posting a follow up article in the coming weeks that covers the actual iOS development. </p>

<p>Our goals for this app are to create an API which will allow us to:</p>

<ul>
<li>Login </li>
<li>Verify a token</li>
<li>Get / Add / Delete to-do items</li>
</ul>

<p>The tools we will use:</p>

<ul>
<li><a href="http://laravel.com/">Laravel</a> - version 4.2</li>
<li><a href="https://github.com/dingo/api">Dingo</a> - RESTful API package</li>
<li><a href="https://github.com/tymondesigns/jwt-auth">JWT Auth</a> - JSON web token auth (works well with <strong>Dingo</strong>)<br><br></li>
</ul>

<p>As always, we encourage you to check out the code on our <a href="https://github.com/kettleio/laravel-token-authentication">Github</a>. It may be helpful to follow along this way.</p>

<hr>

<h1 id="basicframework">Basic Framework</h1>

<p>I'll assume that you already have a standard installation of Laravel 4.2 up and running. If you need to do that first, their site provides a great <a href="http://laravel.com/docs/4.2/quick">quickstart guide</a>.</p>

<h2 id="configuredingojwtauth">Configure Dingo &amp; JWT Auth</h2>

<p>Add both these packages to your composer.json file:  </p>

<pre><code>"dingo/api": "0.8.*",
"tymon/jwt-auth": "0.4.*"
</code></pre>

<p>Then run <code>composer update</code> to grab the repository files.</p>

<h4 id="dingoapi">dingo/api</h4>

<p>We strongly recommend that you <a href="https://github.com/dingo/api/wiki/Installation">read the wiki</a> for this plugin. Here is a quick summary of how to get things up and running:</p>

<ol>
<li>Configure the Provider &amp; Alias inside <code>app/config/app.php</code>  </li>
<li>Publish the package configuration file by running <code>php artisan config:publish dingo/api</code>  </li>
<li>Set the prefix variable to <strong>api</strong>.  </li>
<li><a href="https://github.com/dingo/api/wiki/Authentication#json-web-tokens-jwt">Add JSON web tokens</a> as an authentication provider inside your app/config/packages/dingo/config.php file. The auth array should then look something like this:  </li>
</ol>

<pre><code>'auth' =&gt; [  
    'basic' =&gt; function ($app) {
        return new Dingo\Api\Auth\BasicProvider($app['auth']);
    },
    'jwt' =&gt; function ($app) {
        return new Dingo\Api\Auth\JWTProvider($app['tymon.jwt.auth']);
    }
],
</code></pre>

<p><br></p>

<h4 id="jwtauth">jwt-auth</h4>

<p>The developer for this plugin has a nice <a href="https://github.com/tymondesigns/jwt-auth/wiki/Installation">getting started guide</a> that walks you through installation.</p>

<h2 id="databasedesign">Database Design</h2>

<p>Our goal is to build a to-do list module with authentication. Let's create the necessary tables.</p>

<h4 id="lists">lists</h4>

<p>This table contains the master lists for our users. We can identify the list owner using the <code>user_id</code> column. </p>

<h4 id="todos">todos</h4>

<p>This table contains all the child list items (also know as to-do items). We can identify the parent list using the <code>list_id</code> column. </p>

<h4 id="users">users</h4>

<p>This table will save all the users login information. </p>

<p>We can create all three tables by writing and running a <a href="http://laravel.com/docs/4.2/migrations">migration</a>. Run the artsian command <code>php artisan migrate:make todo_data_structure</code></p>

<p>Then add the following inside the newly created TodoDataStructure class:</p>

<pre><code class="language-php">public function up() {

    Schema::create('lists', function(Blueprint $table) {
        $table-&gt;increments('id');
        $table-&gt;integer('user_id');
        $table-&gt;string('title');
        $table-&gt;timestamps();
    });

    Schema::create('todos', function(Blueprint $table) {
        $table-&gt;increments('id');
        $table-&gt;integer('list_id');            
        $table-&gt;string('title');
        $table-&gt;timestamps();
    });

    Schema::create('users', function(Blueprint $table) {
        $table-&gt;increments('id');
        $table-&gt;string('email')-&gt;unique();
        $table-&gt;string('password');
        $table-&gt;timestamps();
    });     

}

public function down() {  
    Schema::drop('lists');
    Schema::drop('todos');
    Schema::drop('users');
}
</code></pre>

<h2 id="setupmodels">Setup Models</h2>

<p>We will setup 3 models to interact with the API routes and database: User, Todo, TodoList. Add the following to your existing <strong>models/User.php</strong> file:  </p>

<pre><code class="language-php">public function lists() {  
    return $this-&gt;hasMany('TodoList', 'user_id');
}
</code></pre>

<p>Create a new file <strong>models/Todo.php</strong> and add the following:  </p>

<pre><code class="language-php">&lt;?php

class Todo extends Eloquent {

  protected $fillable = ['list_id', 'title'];
  protected $table = 'todos';

  // Get the list of this todo
  public function todoList(){
    return $this-&gt;belongsTo('TodoList', 'list_id');
  }

}
</code></pre>

<p>Create a new file <strong>models/TodoList.php</strong> and add the following:  </p>

<pre><code class="language-php">&lt;?php

class TodoList extends Eloquent {

  protected $fillable = ['user_id', 'title'];
  protected $table = 'lists';

  // Get the todos from this list
  public function todos(){
    return $this-&gt;hasMany('Todo', 'list_id');
  }

}
</code></pre>

<p><br></p>

<hr>

<h1 id="configureapiroutes">Configure API Routes</h1>

<p>At this point you now have a base skeleton for the application up and running. Now its time to code the API routes. We will create an <strong>api</strong> array inside the routes file. This will allow us to protect a route with an auth token by simply adding the <strong>'protected' => true</strong> parameter. The <strong>api</strong> array will look like this:  </p>

<pre><code class="language-php">Route::api('v1', function () {  
});
</code></pre>

<h3 id="loginvalidatetoken">Login &amp; Validate Token</h3>

<p>In order to properly use the token authentication, we will need to code a couple of routes: <strong>login</strong> and <strong>validate_token</strong>. The <strong>login</strong> route will give us a valid token if our user and password is correct. Otherwise, it will just throw an error. Place these routes inside your api array:</p>

<pre><code class="language-php">Route::post('login', [  
    'uses'      =&gt; 'AuthenticateController@authenticate',
    'as'        =&gt; 'api.login'
]);
</code></pre>

<p>The <strong>validate_token</strong> route will check that the token we saved is still valid. We will verify the token everytime the app is opened:</p>

<pre><code class="language-php">Route::get('validate_token',  array(  
    'protected' =&gt; true,
    'as'        =&gt;  'api.validate_token',
    'uses'        =&gt; 'AuthenticateController@validateToken'
));
</code></pre>

<h3 id="todoroutes">Todo Routes</h3>

<p>And finally a the routes for viewing, adding and deleting Todos from each user's list:</p>

<pre><code class="language-php">Route::get('todo', [  
    'uses'      =&gt; 'TodoController@index',
    'as'        =&gt; 'todo.index',
    'protected' =&gt; true
]);

Route::post('todo', [  
    'uses'      =&gt; 'TodoController@store',
    'as'        =&gt; 'todo.store',
    'protected' =&gt; true
]);

Route::delete('todo/{id}', [  
    'uses'      =&gt; 'TodoController@destroy',
    'as'        =&gt; 'todo.destroy',
    'protected' =&gt; true
]);                
</code></pre>

<p><br></p>

<hr>

<h1 id="controllers">Controllers</h1>

<p>Let's code the methods for our controllers: AuthController and TodoController.</p>

<h3 id="authcontroller">AuthController</h3>

<p>This particular controller will need two methods. First, the authenticate method will verify the user email and password. If the credentials are valid it will generate a token and return it as JSON. If the credentials are not valid it will return a 401 error with the message "invalid_credentials".</p>

<p>Second, the validate_token method is used to verify the validity of the token. If the token is still valid it will return a success message. If the token is not valid, it will return an error exception based on the JWT errors.</p>

<p>To accomplish this we will create a new file <code>controllers/AuthenticateController.php</code> and put the following code in it:</p>

<pre><code class="language-php">&lt;?php  
use Tymon\JWTAuth\Exceptions\JWTException;

class AuthenticateController extends \BaseController{

  public function authenticate() {

    // Get credentials from the request
    $credentials = Input::only('email', 'password');

    try {
      // Attempt to verify the credentials and create a token for the user.
      if (! $token = JWTAuth::attempt($credentials)) {
        return API::response()-&gt;array(['error' =&gt; 'invalid_credentials'])-&gt;statusCode(401);
      }
    } catch (JWTException $e) {
      // Something went wrong - let the app know.
      return API::response()-&gt;array(['error' =&gt; 'could_not_create_token'])-&gt;statusCode(500);
    }

    // Return success.
    return compact('token');
  }

  public function validateToken(){
    return API::response()-&gt;array(['status' =&gt; 'success'])-&gt;statusCode(200);
  }

}
?&gt;         
</code></pre>

<h3 id="todocontroller">TodoController</h3>

<p>This particular controller will need a method for each todo action: add and delete.</p>

<p>Create a new file <code>controllers/TodoController.php</code> and put the following code in it:</p>

<pre><code class="language-php">&lt;?php

class TodoController extends \BaseController{

  public function index(){

    $user = API::user();
    $userList = TodoList::find($user-&gt;lists()-&gt;first()-&gt;id);

    if($userList){

      $todos = $userList-&gt;todos()-&gt;get();

      return API::response()-&gt;array(['status' =&gt; 'success', 'todos' =&gt; $todos ]);

    }

    return API::response()-&gt;array(['status' =&gt; 'failed', 'message' =&gt; 'There was an error. Please try again.' ])-&gt;statusCode(401);

  }

  public function store(){

    $validation = Validator::make(Input::all(), [
      'title' =&gt; 'required'
    ] );

    if($validation-&gt;fails()){
      return API::response()-&gt;array(['status' =&gt; 'failed', 'message' =&gt; $validation])-&gt;statusCode(200);
    }

    $user = API::user();

    $userList = TodoList::find($user-&gt;lists()-&gt;first()-&gt;id);

    try{

      $todo = new Todo([
        'title'    =&gt; Input::get('title'),
      ]);

      $todo-&gt;save();

      if($todo &amp;&amp; $userList){
        $userList-&gt;todos()-&gt;save($todo);
      }

      return API::response()-&gt;array(['status' =&gt; 'success', 'message' =&gt; 'Todo was added!']);

    } catch(\Exception $e){

        return API::response()-&gt;array(['status' =&gt; 'failed', 'message' =&gt; 'There was an error. Please try again.' ])-&gt;statusCode(401);

    }

  }

  public function destroy($id){

    $user = API::user();
    $userList = TodoList::find($user-&gt;lists()-&gt;first()-&gt;id);

    $todo = Todo::find($id);

    if($todo &amp;&amp; $todo-&gt;list_id == $userList-&gt;id){

      $todo-&gt;delete();

      return API::response()-&gt;array(['status' =&gt; 'success', 'message' =&gt; "Todo was deleted." ])-&gt;statusCode(200);

    }

    return API::response()-&gt;array(['status' =&gt; 'failed', 'message' =&gt; 'There was an error. Please try again.' ])-&gt;statusCode(401);

  }

}

?&gt;                
</code></pre>

<p><br></p>

<hr>

<h1 id="testing">Testing</h1>

<p>Now that we have all the code in place, lets make sure its working correctly. </p>

<h3 id="manuallycreateusertodolist">Manually Create User &amp; Todo List</h3>

<p>First you will need to add a user to the database. Run the following SQL command, or manually insert a user into the database:  </p>

<pre><code class="language-shell">INSERT INTO `users` (`id`, `email`, `password`, `created_at`, `updated_at`)  
VALUES (1, 'hello@kettle.io', '[password]', '2015-06-16 02:32:51', '2015-06-16 02:32:51');  
</code></pre>

<p><br></p>

<p>Note that we will need to generate a hashed password in place of [password]. Since this is dependent on your installations app key you can generate a password through the <code>artisan tinker</code> command.</p>

<ol>
<li>Move to your project directory and run the <code>php artisan tinker</code> command  </li>
<li>Generate a password using the following command <code>echo Hash::make('abc123');</code>  </li>
<li>Copy the output and use it in the password column of your database.</li>
</ol>

<p>Next, we need to add a new list to the database and associate it with our user. Once we've built the iOS app these lists will be dynamically generated in the database. However, for the purposes of testing we will need to manually add a list. Run the following SQL command, or manually insert a user into the database (assuming your newly created user has the ID 1):  </p>

<pre><code class="language-shell">INSERT INTO `lists` (`id`, `user_id`, `title`, `created_at`, `updated_at`)  
VALUES (1, 1, 'Test List', '2015-06-16 02:32:51', '2015-06-16 02:32:51');  
</code></pre>

<p><br></p>

<h3 id="generatetoken">Generate Token</h3>

<p>Now that you have created a user and todo list lets go ahead and ensure that the app is creating and validating tokens correctly. For this I prefer to use a Chrome extension called <a href="https://www.getpostman.com/">Postman</a>. You'll need to send a <strong>POST</strong> request to the <code>/api/login</code> route including the email and password. If you recieve a token back, everything is working as expected. You'll use this token to authenticate subsequent calls to the API. It should look something like this in Postman:</p>

<p><img src="https://blog.kettle.io/content/images/2015/06/create-token.png" alt="Token Authentication Using Laravel + iOS"></p>

<h3 id="createtodoitem">Create Todo Item</h3>

<p>Send a <strong>POST</strong> request to <code>/api/todo</code> with your token as a query string and the desired todo title as a form input. This will create the todo item in your database and map it to the specified user. For simplicity sake, each user only has one list. It will look like this:</p>

<p><img src="https://blog.kettle.io/content/images/2015/06/create-todo.png" alt="Token Authentication Using Laravel + iOS"></p>

<h3 id="viewtodos">View Todos</h3>

<p>Send a <strong>GET</strong> request to <code>/api/todo</code> with your token as a query string. This will return a JSON object with all the todo items for that particular user. It will look like this:</p>

<p><img src="https://blog.kettle.io/content/images/2015/06/view-todo.png" alt="Token Authentication Using Laravel + iOS"></p>

<h3 id="deletetodoitem">Delete Todo Item</h3>

<p>Send a <strong>DELETE</strong> request to <code>/api/todo/{id}?token=yourtoken</code> - where ID is the ID of the todo item you wish to delete. It should look something like this:</p>

<p><img src="https://blog.kettle.io/content/images/2015/06/delete-todo.png" alt="Token Authentication Using Laravel + iOS" title=""><br></p>

<hr>

<h1 id="conclusion">Conclusion</h1>

<p>Thanks for reading. Please visit again for our follow up article on the iOS portion of this project.</p>

<p>If you have any comments or questions please leave them below. Remember you can also report issues and download this project directly from our <a href="https://github.com/kettleio/laravel-token-authentication">Github</a>.</p>]]></content:encoded></item><item><title><![CDATA[Building an API with Go (and how it compares to Laravel)]]></title><description><![CDATA[<h1 id="welcome">Welcome</h1>

<p>There has been a lot of buzz around <a href="https://golang.org/">Go (golang)</a> lately. I don't tend to be an earlier adopter for new languages since a strong community and proven platform are critical when building software intended for production enviroments. </p>

<p>Go has matured quite a bit since it was introduced in</p>]]></description><link>https://blog.kettle.io/building-an-api-with-go-and-how-it-compares-to-laravel/</link><guid isPermaLink="false">08b04f94-25b5-4561-8d7e-e5514920d214</guid><dc:creator><![CDATA[Drew Witmer]]></dc:creator><pubDate>Wed, 18 Mar 2015 16:07:33 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/03/f582ea280b53e35e9737fb81469a14dd362d9644.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="welcome">Welcome</h1>

<img src="http://blog.kettle.io/content/images/2015/03/f582ea280b53e35e9737fb81469a14dd362d9644.jpg" alt="Building an API with Go (and how it compares to Laravel)"><p>There has been a lot of buzz around <a href="https://golang.org/">Go (golang)</a> lately. I don't tend to be an earlier adopter for new languages since a strong community and proven platform are critical when building software intended for production enviroments. </p>

<p>Go has matured quite a bit since it was introduced in 2007, so I decided to take a deeper look this week. My research concluded that it makes a good fit for scalabale (enterprise level) web apps, and API's in specific. </p>

<p>Go supports concurrency and multi-threading on the language level, right out of the box. It also enforces strict syntax and formatting rules - making your code more standardized and less error prone. There are other advantages like built in testing tools and fast compiling speed, but I won't harp on those too much. I don't consider either of those a differentiating factor.</p>

<p>I wanted to give Go a try and build a practical application that we would normally develop here at <a href="http://kettle.io">Kettle</a>. A simple API, hooked up to MySQL seemed like the perfect concept. </p>

<p>Lets do this!</p>

<hr>

<h1 id="prerequisites">Prerequisites</h1>

<p>Since I wanted to test the full life cycle of a Go application I needed to setup a remote enviroment on Heroku. I won't go into too much detail on how to set these up, but below are some resources that I found <em>extremely</em> helpful:</p>

<ul>
<li>Setting up Go locally on a Mac isn't very straight forward. You can use Homebrew here, but I'd suggest referencing the <a href="https://golang.org/doc/install">Offical Site</a> &amp; <a href="http://www.ryanday.net/2012/10/01/installing-go-and-gopath/">Ryan Day's Guide</a></li>
<li>Setting up Go with Heroku was pretty straight forward using <a href="https://mmcgrana.github.io/2012/09/getting-started-with-go-on-heroku.html">Mark McGranaghan's guide</a></li>
</ul>

<h2 id="thecode">The Code</h2>

<p>I found a nifty framework called <a href="https://github.com/go-martini/martini">Martini</a> that was designed to make the code more modular and quicker to write. I came up with the following code for my super simple sudo-API:</p>

<pre><code class="language-go">package main

import (  
    "github.com/go-martini/martini"
    _ "github.com/go-sql-driver/mysql"
    "database/sql"
    "fmt"
)

func main() {

    // Connect to database
    db, err := sql.Open("mysql",
        "user:pass@tcp(localhost:3306)/tableName")


    // Fire up martini &amp; define route
    m := martini.Classic()
    m.Get("/api/:id", func(params martini.Params) string {   

          // Define variables
          var str string
          var userId =  params["id"]

          // Run MySQL query against param
          err = db.QueryRow(
              "select name from users where id = ?", userId).Scan(&amp;str)


          // Check for errors and log if they exist     
          if err != nil &amp;&amp; err != sql.ErrNoRows {
              fmt.Println(err)
          } 

          return str 

    })

  m.Run()
  defer db.Close()

}
</code></pre>

<h2 id="justhowfastisit">Just How Fast Is It?</h2>

<p>Now that I had a functioning piece of Go code I wanted to see just how fast the language was. After hearing all the praises of the language I needed to see first hand how good/bad it was. </p>

<p>To test the app I used a service called <a href="http://loader.io/">Loader.io</a> (awesome tool by the way). I had Loader query the service with 4,000 clients (making 2 requests each) over the course of 60 seconds and these are the results I saw:</p>

<div style="width: 800px;">  
<iframe width="800" height="400" frameborder="0" src="//share.loader.io/reports/538ca4ecbe09f388b15c6a5df9c016d3/widget/results/d3cd4d906c7d4f58ce81ac5ace24b616"></iframe></div>

<p>The results are astounding. I was running a <em>free</em> Heroku instance and <em>free</em> database from ClearDB. Regardless of those limitations, the app managed an average response of 35ms with <b>zero</b> errors. I found this impressive for three reasons: </p>

<ul>
<li>The response times were quick and consistent</li>
<li>The error rate was zero which is important</li>
<li>The app handled many requests per second on limited server resources without issue (think: cheap infastructure costs at scale)</li>
</ul>

<h2 id="comparedtolaravel5">Compared to Laravel 5</h2>

<p>My intention here was to learn Go and see if it was really as good as people said. After seeing the results, I'm pretty convinced it is good. However, I was curious to see how it would stack up against <a href="http://laravel.com">Laravel 5</a>, an awesome PHP framework we use quite often here at <a href="http://kettle.io">Kettle</a>. I knew this wasn't a fair comparision, but I did it anyway. Here is the code we used in Laravel:</p>

<p><strong>routes.php</strong></p>

<pre><code class="language-php">&lt;?php

Route::get('/', 'WelcomeController@index');  
Route::get('/api/{user}', 'ApiController@user');  
</code></pre>

<p><strong>ApiController.php</strong></p>

<pre><code class="language-php">&lt;?php 

namespace App\Http\Controllers;  
use DB;

class ApiController extends Controller {

    public function user($user) {
        $response = DB::table('users')-&gt;where('id', $user)-&gt;first();

        return $response-&gt;name;
    }

}
</code></pre>

<p>I ran the same test again - 4,000 clients over the course of 60 seconds, each making 2 requests. These are the results observed:</p>

<div style="width: 800px;">  
<iframe width="800" height="400" frameborder="0" src="//share.loader.io/reports/1b93311335087c0b4408367a1a8ecaf1/widget/results/02ce1b39bab0ea96dc2c679b84b605da"></iframe></div>

<h2 id="conclusion">Conclusion</h2>

<p>As expected, Laravel performed much slower than Go. I believe Go is a great choice for something like an enterprise API. It's quick and predicable. This makes it easy to scale.</p>

<p>Laravel has it's place too - it allows us to build robust web apps, quickly. That makes it a great fit for projects that require quick turn around and agile development.</p>

<p>We hope you enjoyed this article. Please feel free to leave comments below.</p>]]></content:encoded></item><item><title><![CDATA[Add Dummy Content Using Laravel + Faker]]></title><description><![CDATA[<h1 id="welcome">Welcome</h1>

<p>One part of testing any application is seeing how it reacts to a volume of data. When building an application with Laravel, we use a great package called <a href="https://github.com/fzaninotto/Faker">Faker</a> to make this process quick. Their API allows us to painlessly add a ton of content to our application.</p>

<p>This</p>]]></description><link>https://blog.kettle.io/seed-a-laravel-database-with-faker/</link><guid isPermaLink="false">74256ffe-a2ff-4f2c-b002-0716b7befc0f</guid><dc:creator><![CDATA[Adan Archila]]></dc:creator><pubDate>Tue, 24 Feb 2015 18:02:06 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/02/e956ac9b5a2b00841051c1c60cd390a2.jpeg" medium="image"/><content:encoded><![CDATA[<h1 id="welcome">Welcome</h1>

<img src="http://blog.kettle.io/content/images/2015/02/e956ac9b5a2b00841051c1c60cd390a2.jpeg" alt="Add Dummy Content Using Laravel + Faker"><p>One part of testing any application is seeing how it reacts to a volume of data. When building an application with Laravel, we use a great package called <a href="https://github.com/fzaninotto/Faker">Faker</a> to make this process quick. Their API allows us to painlessly add a ton of content to our application.</p>

<p>This is an add-on to our previous post <a href="http://blog.kettle.io/dynamic-pagination-angularjs-laravel/">Dynamic Pagination using Laravel &amp; AngularJS</a> and will show you how to add 50 "fake" posts to your application for testing.</p>

<p>The tools we will use:</p>

<ul>
<li><a href="https://github.com/laravel/laravel/releases/tag/v4.2.11">Laravel 4.2</a></li>
<li><a href="https://github.com/fzaninotto/Faker">Faker</a></li>
</ul>

<hr>

<h1 id="letsgetstarted">Let's Get Started</h1>

<p>I will assume that you already have a database setup. I will also assume you've created a <strong>posts</strong> table with the following structure:</p>

<ul>
<li>id</li>
<li>title</li>
<li>content</li>
</ul>

<h2 id="installfaker">Install Faker</h2>

<p>Our fist step will be to install Faker within our Laravel application. You'll need to use  <a href="https://getcomposer.org/">composer</a> to install the package. Either through terminal or  the composer.json file.</p>

<p><strong>Using Terminal</strong></p>

<ol>
<li><code>cd /Directory-of-Laravel-App</code>  </li>
<li><code>sudo composer require fzaninotto/faker --dev</code></li>
</ol>

<p><strong>Using composer.json</strong></p>

<ol>
<li>Open up your <strong>composer.json</strong> file.  </li>
<li>Add the following snippet to your <strong>require-dev</strong> array: <code>"fzaninotto/faker": "1.3.*@dev"</code>  </li>
<li><code>cd /Directory-of-Laravel-App</code>  </li>
<li>Run the command <code>composer update</code></li>
</ol>

<h2 id="createseederfiledefinedata">Create Seeder File &amp; Define Data</h2>

<p>The next step is to create a file which will generate the fake data for us. Since we are trying to seed the posts table, lets go ahead and create a file called <strong>PostsTableSeeder.php</strong> inside <code>app/database/seeds/</code>. Faker adds on to the existing seeder class that ships with Laravel.</p>

<p>The best part of Faker is the flexability of its API. We can easily insert sentences, paragraphs, images, dates, names, phone numbers and more. A complete list of content types is available <a href="https://github.com/fzaninotto/Faker">here</a>. </p>

<p>As you'll see we opted to use the sentence (post title) and paragraph (post description) content types.</p>

<pre><code class="language-php">&lt;?php

use Faker\Factory as Faker;

class PostsTableSeeder extends Seeder {

    public function run() {
        $faker = Faker::create();

        foreach(range(1, 50) as $index) {
            Post::create([
                'title'     =&gt; $faker-&gt;sentence(5),
                'content'   =&gt; $faker-&gt;paragraph(4)
            ]);
        }
    }
}
</code></pre>

<h2 id="addtoseederclass">Add to Seeder Class</h2>

<p>Our last step (I told you Faker made this quick), is to add the Posts seeder we just created to our master seeder class. Go ahead and edit the file <strong>DatabaseSeeder.php</strong> within <code>app/database/seeds/</code>. </p>

<p>Assuming you haven't made any changes to the existing class, your file should look like this:</p>

<pre><code class="language-php">&lt;?php

use Illuminate\Database\Seeder;  
use Illuminate\Database\Eloquent\Model;

class DatabaseSeeder extends Seeder {

    public function run() {
        Model::unguard();
        DB::table('posts')-&gt;truncate(); //If you want to reset to 50. See note below.
         $this-&gt;call('PostsTableSeeder');
    }
}
</code></pre>

<p>Now everytime you run <code>php artisan db:seed</code> in your terminal you will be adding 50 more posts to your database. </p>

<p><strong>Note:</strong> If you don't want to keep adding 50 additional posts everytime you run <code>db:seed</code> you will want to include this line of code. It will remove the previous database entries before inserting the new dummy content.</p>

<p>Obviously we are using this library within a test enviroment. So when you move the application to production you will most certainly want to remove the <code>truncate();</code> function from your code. Otherwise you may accidentaly run <code>db:seed</code> and erase data from your production database. </p>]]></content:encoded></item><item><title><![CDATA[Dynamic Pagination using Laravel & AngularJS]]></title><description><![CDATA[<h1 id="welcome">Welcome!</h1>

<p>Today we will be combining the <a href="http://laravel.com/">Laravel</a> framework with Google's <a href="https://angularjs.org/">Angular JS</a>. This has a variety of uses, but our article will show you how to setup posts within a blog. We will be implementing dynamic pagination using the built in  Laravel <a href="http://laravel.com/docs/pagination">paginate</a> option. </p>

<p>At the time of this</p>]]></description><link>https://blog.kettle.io/dynamic-pagination-angularjs-laravel/</link><guid isPermaLink="false">84f270c1-94b7-41fa-8c7e-e19ca3aefec9</guid><dc:creator><![CDATA[Adan Archila]]></dc:creator><pubDate>Thu, 15 Jan 2015 22:53:41 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/01/shapes.png" medium="image"/><content:encoded><![CDATA[<h1 id="welcome">Welcome!</h1>

<img src="http://blog.kettle.io/content/images/2015/01/shapes.png" alt="Dynamic Pagination using Laravel & AngularJS"><p>Today we will be combining the <a href="http://laravel.com/">Laravel</a> framework with Google's <a href="https://angularjs.org/">Angular JS</a>. This has a variety of uses, but our article will show you how to setup posts within a blog. We will be implementing dynamic pagination using the built in  Laravel <a href="http://laravel.com/docs/pagination">paginate</a> option. </p>

<p>At the time of this post we were unable to find existing documentation on this approach. We are making this post in hopes that you find it helpful. The <a href="https://github.com/kettleio/laravel-angular-pagination">entire code</a> can be found on our <a href="https://github.com/kettleio">GitHub</a>.</p>

<p><b>Tools</b> <br>
For this article we will be using the following tools. It's important that you are familar with the frameworks in order to use the system to it's full advantages.</p>

<ul>
<li><a href="https://angularjs.org/">AngularJS</a> JS framework (we used 1.3.0)</li>
<li><a href="http://laravel.com/">Laravel</a> PHP framework (we used 4.2)</li>
<li><a href="http://getbootstrap.com/">Twitter Bootstrap</a> - HTML/CSS framework</li>
</ul>

<hr>

<h1 id="letsgetstarted">Let's Get Started</h1>

<p>I'll assume that you already have a standard installation of Laravel up and running. If you need to do that first, their site provides a great <a href="http://laravel.com/docs/4.2/quick">quickstart guide</a>.</p>

<h2 id="createroutesviews">Create Routes &amp; Views</h2>

<p>First we will create the routes and view needed to show your blogs posts. We'll build something simple using the grid styles provided by Bootstrap. You can customize this later once the system is hooked up. In this example we'll include 5 posts and next/back buttons.</p>

<p>Inside the routes file we will add a route for the JSON data and one for the actual posts page. Add the following to your <code>app/routes.php</code> file.</p>

<pre><code class="language-php">Route::get('posts', function() {  
    return Response::view('posts');
});

Route::get('posts-json', array(  
  'as' =&gt; 'posts-json', 
  'uses' =&gt; 'PostController@json' 
));
</code></pre>

<p><br> <br>
Create a new file called <code>posts.blade.php</code> in <code>/app/views</code> and place the following code in it. Note that we have included the Bootstrap library.</p>

<pre><code class="language-html">&lt;!DOCTYPE html&gt;  
&lt;html lang="en"&gt;  
  &lt;head&gt;
    &lt;link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"&gt;
    &lt;title&gt;My Blog&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;  
    &lt;div class="col-md-6 col-md-offset-3"&gt;  
      &lt;h2&gt;Posts&lt;/h2&gt;

    &lt;/div&gt; 
  &lt;/body&gt;  
&lt;/html&gt;  
</code></pre>

<h2 id="createdatabasetablecontroller">Create Database Table &amp; Controller</h2>

<p>We will create a new model for our posts. We will name the new model <strong>Post</strong>. We will also create a new table to save all my posts with some basic structure. We will call this table <strong>posts</strong> and give it columns for: </p>

<ul>
<li>ID (auto-increment)</li>
<li>Title (varchar, 100)</li>
<li>Content (varchar, 255)</li>
</ul>

<p>You should really use <code>php artisan migrate:make create_posts_table</code> here but I won't go into detail on that. Hopefully your familar with the built in <a href="http://laravel.com/docs/4.2/migrations">migrations</a>.</p>

<p>Now that we have the posts table setup we are going to populate it with some data. For testing I like to use the <a href="https://github.com/fzaninotto/Faker">Faker library</a>. If you are unfamiliar with how to use Faker I suggest taking a look at our article on <a href="https://blog.kettle.io/dynamic-pagination-angularjs-laravel/#">how to seed a database with dummy data in Laravel</a>. </p>

<p>Now that we have the database table created and populated, lets create a controller for the posts. We will use this to paginate through the posts and fetch their data. We will create a new file in the <code>app/controllers</code> folder and call it <b>PostController.php</b>. Inside we will create a new function <code>json</code>  that will geneate the JSON data:</p>

<pre><code class="language-php">&lt;?php  
class PostController extends BaseController {

    public function json(){  
        $posts = Post::paginate(5); // 5 is the number of items to show per page
        return Response::json($posts);
    }

}
</code></pre>

<h2 id="createpostmodel">Create "post" Model</h2>

<p>We will now create a post model to connect our new controller to the post table. Create a new file called <code>Post.php</code> in the <code>app/models</code> directory. Inside the new file add the following code.</p>

<pre><code>&lt;?php

class Post extends Eloquent  {  
    protected $fillable = ['title', 'content'];
    protected $table = 'posts';
    protected $hidden = array();
}
</code></pre>

<h2 id="addconfigureangularjs">Add &amp; Configure AngularJS</h2>

<p>It is time to add AngularJS to the page and unlock all the potential that this framework can offer. Go ahead and include the library in your page. You will also need to create a JS file to place your code.  </p>

<pre><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"&gt;&lt;/script&gt;  
&lt;script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-resource.min.js"&gt;&lt;/script&gt;  
&lt;script src="js/app.js"&gt;&lt;/script&gt;  
</code></pre>

<p><b>Important!</b> <br>
Laravel's blade templates use the same opening/closing brackets as AngularJS <strong>{{ }}</strong>. We must configure AngularJS to use <strong>[[ ]]</strong> instead to avoid conflicts. We can do that by adding the following code to our newly created <code>js/app.js</code> file.</p>

<pre><code class="language-javascript">var app = angular.module('kettle', ['ngResource'],  
 function($interpolateProvider) {
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
});
</code></pre>

<h2 id="configureviewfile">Configure View File</h2>

<p>Now that we have enabled AngularJS lets modify the HTML view to render it. Please note that we have now included <strong>ng-app</strong> in the body tag. This is critical.</p>

<pre><code>  &lt;body ng-app="kettle"&gt;  
    &lt;div class="col-md-6 col-md-offset-3" ng-controller="postController" ng-init="getPosts()"&gt;  

      &lt;h2&gt;Posts&lt;/h2&gt;

      &lt;div class="list-group" &gt;  
        &lt;a href="#" class="list-group-item" ng-repeat="post in posts" &gt;
          &lt;h4 class="list-group-item-heading"&gt;[[ post.title ]]&lt;/h4&gt;
          &lt;p class="list-group-item-text"&gt;[[ post.content ]]&lt;/p&gt;
        &lt;/a&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;posts-pagination&gt;&lt;/posts-pagination&gt;
      &lt;/div&gt;

    &lt;/div&gt;  
  &lt;/body&gt;  
</code></pre>

<p>You will notice that we have used the <posts-pagination> directive in place of buttons. This will allow us to define the pagination based on the bootstrap styles inside our <code>js/app.js</code> file.</posts-pagination></p>

<pre><code class="language-javascript">app.directive('postsPagination', function(){  
   return{
      restrict: 'E',
      template: '&lt;ul class="pagination"&gt;'+
        '&lt;li ng-show="currentPage != 1"&gt;&lt;a href="javascript:void(0)" ng-click="getPosts(1)"&gt;&amp;laquo;&lt;/a&gt;&lt;/li&gt;'+
        '&lt;li ng-show="currentPage != 1"&gt;&lt;a href="javascript:void(0)" ng-click="getPosts(currentPage-1)"&gt;&amp;lsaquo; Prev&lt;/a&gt;&lt;/li&gt;'+
        '&lt;li ng-repeat="i in range" ng-class="{active : currentPage == i}"&gt;'+
            '&lt;a href="javascript:void(0)" ng-click="getPosts(i)"&gt;{{i}}&lt;/a&gt;'+
        '&lt;/li&gt;'+
        '&lt;li ng-show="currentPage != totalPages"&gt;&lt;a href="javascript:void(0)" ng-click="getPosts(currentPage+1)"&gt;Next &amp;rsaquo;&lt;/a&gt;&lt;/li&gt;'+
        '&lt;li ng-show="currentPage != totalPages"&gt;&lt;a href="javascript:void(0)" ng-click="getPosts(totalPages)"&gt;&amp;raquo;&lt;/a&gt;&lt;/li&gt;'+
      '&lt;/ul&gt;'
   };
});
</code></pre>

<h2 id="fetchparsejsonusingangularjs">Fetch &amp; Parse JSON Using AngularJS</h2>

<p>If you remember in the beginning we created the route <strong>/posts-json/</strong> to serve up the post information using JSON. Now its time to use it. When you load that page you should see something like this.</p>

<p><img src="https://blog.kettle.io/content/images/2015/01/json-response.png" alt="Dynamic Pagination using Laravel & AngularJS"></p>

<p>The <strong>data</strong> key in the JSON is the one that holds the content of all our posts. When we paginate with Laravel all we need to do is add a <strong>page</strong> parameter to the URL and Laravel will handle the rest. For example, <strong>/posts-json?page=2</strong> would yield the second page of results. </p>

<p>Now its time to write the code snippet for AngularJS that will fetch and parse the JSON + enable the pagination functions. This requires that we write a new controller called <strong>postController</strong> in our <strong>app.js</strong> file.</p>

<p><strong>Update!</strong> We've updated the code below to use pagination with ngResource. We'll leave the old code commented inline, in case you want to continue using that!</p>

<pre><code class="language-javascript">app.factory( 'Post', function($resource){  
  return $resource('post');
});

app.controller('postController', [ '$http', '$scope', function($http, $scope){

  $scope.posts = [];
  $scope.totalPages = 0;
  $scope.currentPage = 1;
  $scope.range = [];

  $scope.getPosts = function(pageNumber){

    if(pageNumber===undefined){
      pageNumber = '1';
    }
    Post.get({page: pageNumber},function(response){
    // Old pagination style using http
    // $http.get('/posts-json?page='+pageNumber).success(function(response) { 

      $scope.posts        = response.data;
      $scope.totalPages   = response.last_page;
      $scope.currentPage  = response.current_page;

      // Pagination Range
      var pages = [];

      for(var i=1;i&lt;=response.last_page;i++) {          
        pages.push(i);
      }

      $scope.range = pages; 

    });

  };

}]);
</code></pre>

<p>Once you've added this code you should see the final result by visiting the <strong>/posts</strong> you created in the beginning. If everything went smooth your final result should look something like this: </p>

<p><img src="https://blog.kettle.io/content/images/2015/01/final-result.png" alt="Dynamic Pagination using Laravel & AngularJS"></p>

<hr>

<h1 id="summary">Summary</h1>

<p>We hope this article was helpful to you. If you have any comments please leave them below - thanks!</p>]]></content:encoded></item><item><title><![CDATA[New Year. New Blog.]]></title><description><![CDATA[<p>Today we are launching our blog. This marks a new addition to our business and is something we plan to contribute to on a regular basis moving forward in 2015. </p>

<p>You can expect a new post every 3-4 weeks. I expect the blog to consist of a few different things</p>]]></description><link>https://blog.kettle.io/our-new-blog/</link><guid isPermaLink="false">65647267-8e84-4a28-99e4-d36093cc88a1</guid><dc:creator><![CDATA[Drew Witmer]]></dc:creator><pubDate>Wed, 07 Jan 2015 00:22:22 GMT</pubDate><media:content url="http://blog.kettle.io/content/images/2015/01/DSCF2988-Edit.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.kettle.io/content/images/2015/01/DSCF2988-Edit.jpg" alt="New Year. New Blog."><p>Today we are launching our blog. This marks a new addition to our business and is something we plan to contribute to on a regular basis moving forward in 2015. </p>

<p>You can expect a new post every 3-4 weeks. I expect the blog to consist of a few different things for the forseeable future:</p>

<ol>  
<li>Tutorials walking you through a development issue we faced this month.</li>  
<li>How we made business or dev-ops related decisions.</li>  
<li>Kettle projects and Kettle client news!</li>  
</ol>

<p>I hope to see our blog expand and evolve beyond this...with the help and guidance of our readers of course! </p>

<p>Until next time.</p>]]></content:encoded></item></channel></rss>