Thursday, 1 August 2013

node.js + coffeescript in a nutshell

Here's is a quick 101 on getting Node.js/CoffeeScript up on Ubuntu Server I'm using Ubuntu 13.10 that contains Node.js in its default repositories. *Note that this will not be the newest one. However it's the simplest way of getting started.

We just have to use the apt package manager. We should refresh our local list packages before installing:

sudo apt-get update

sudo apt-get install nodejs

This is all that you need to do to get set up with Node.js. You will also need to install npm(Node.js Package Manager).

sudo apt-get install npm

This will allow you to easily install modules and packages to use with Node.js.

Because of a conflict with another package, the executable from the Ubuntu repositories is called nodejs instead of node. It's just good to keep this in mind.

The last step is to install the CoffeeScript interpreter

npm install coffee-script

Now that we are setup. Here is a basic node HelloWorld server written in coffee. File: index.coffee
http = require "http"
url = require "url"

start = () ->
 onRequest = (request, response) ->
  pathname = url.parse(request.url).pathname
  console.log ("Request for #{pathname}")
  
  response.writeHead (200),
  "Content-Type": "text/plain"

  response.write "Code Sandwich"
  response.end()
 
 http.createServer(onRequest).listen (8888)

 console.log ("Server has started.")
 
start()

Ladies start your servers.

coffee index.coffee

now check that this is all ok

localhost:8888
... continue reading!

Coffee to S3

It's late, I have tron on in the background and am thinking of how to make the Grid a reality.. may not be something I can come up with tonight :/

..what else is on my mind...

I'm pushing things to Amazon's Simple Storage Service(S3) but would be good to automate them.


Coffee time! and I'm not just saying that because its late. ok, bad pun

Next we need to install the AWS SDK(more info on AWS SDK for node.js).

console:

npm install aws-sdk
Now you will need to get your AWS access info

First login to your Amazon account at http://aws.amazon.com

Once logged in go to the top right, click on your name and then click "Security Credentials"







Next you will need to go to you Access Keys and click "Create New Root Key"



Next you will be prompted with the "Create Access Key". [This will invalidate your old key]
download the 'Key File' to access your newly generated key.




back to the editor and create two new files config.json and  aws.coffee

file config.json


{ "accessKeyId": " AWSAccessKeyId goes here ", "secretAccessKey": " AWSSecretKey goes here ", "region": "us-west-2" }

file aws.coffee

#load the aws sdk
AWS = require('aws-sdk')

#load the keys to access your account
AWS.config.loadFromPath './config.json'

#lets create an object to connect to S3
s3 = new AWS.S3()

#As buckets names are shared across all account in a region
#Let create a random number so multiple people can run this example
ran = Math.random()

#call the createBucket function and add a file
s3.createBucket
 Bucket: "codemeasandwich#{ran}"
, ->
 params =
  Bucket: "codemeasandwich#{ran}"
  Key: "aFile"
  Body: "HelloWorld"

 s3.putObject params, (err, data) ->
  if err
   console.log err
  else
   console.log data
   console.log "Successfully uploaded data to myBucket/myKey"


Now lets fire up the console and run our "aws.coffee"

console:
coffee aws.coffee
now check that this is all ok

... continue reading!

Monday, 15 July 2013

HTML form on a static site

So my mission right now is to see how far I can push my luck with hosting from Amazon's S3(Simple Storage Service). 

For anyone from the ice age. Think of S3 like a HTTP wrapper around and FTP server. If you're wondering why anyone would want to use this over a normal server... then just google S3. Anyway back to business!

My ingredients for today *lick lips*
  1. Host a static site (requirement of S3)
  2. Record input to google docs
  3. Consistent styling across the site
Now "google doc" supports a document type of Form that allows you to create a set of questions that people can fill out and have all the answers collected in a spreadsheet layout. 

When you start to create a Form you will be presented with the following.. Pretty!!



For this to work you have to leave it on the default theme.


You will need to make the form public.




Add some Questions.. if you're into that sort of thing!




When Done you'll get the below form


 but what you're really looking for is the embed URL


With the link copyed, back to your site.. *Zoom*

With the iframe tag in our page we get the following:



Not very nice :p

let's take a look at the code we have so far:


<html>
<head>
<style>
body
{
background-image:url('/Wood_tile_wallpaper_by_neko_xexe.png');
}
</style>
</head>
<body>
<iframe frameborder="0" height="500" marginheight="0" marginwidth="0" src="https://docs.google.com/a/codemeasandwich.com/forms/d/1NktonTf4ss3xDagjb-656PV1SBbLanfSbeP2zfRj7ds/viewform?embedded=true" width="760">Loading...</iframe>
</body>
</html>

To make this look more inline with our site we are going to need a bit more information about how google has put together this form.


Once the new page has loaded. Right click to view the source


In the source you need to find the form tag. Now copy the tag and all its content.



back on our site page, replace the iframe tag with the below

<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;"></iframe>


Now paste the form code under the iframe tag. You will need to change the target tag to "hidden_iframe"


That definitely looks a bit better and I didn't need any server side :D

P.s. I have some Ideas for a follow-up post on how to better style your form +using the new HTML5 input tags and some small javascript tips to really make your form rock.
So let me know if that's something you guys are interested in.
... continue reading!

Monday, 8 July 2013

Code Completion with Magic Methods

Recently I was told that a code example that used the "__call" didn't work. As he couldn't call the function I had outlined outside of my example code?

Weird!!

This was down to eclipse's  auto-completion only listing the functions that are declared in the class source.. and on paper that seems normal. 
Unfortunately when dealing with a dynamic type language like PHP this won't cut it!

So how can we address for our auto-completion and document generation friends?

Example time: (the below is straight from the PHPDocs)

/**
 * show off @method
 *
 * @method int borp() borp(int $int1, int $int2) multiply two integers
 */
class Magician
{
    function __call($method, $params)
    {
        if ($method == 'borp') {
            if (count($params) == 2) {
                return $params[0] * $params[1];

            }
        }
    }
}
... continue reading!

Tuesday, 11 June 2013

Coffeescript for PHP developers


Well I decided to teach my self Coffeescript and was hoping to find a little tutorial for people coming from a PHP background, but was surprised when the internet came up short.
Well, see a need.. fill a need!

So heres a few examples from Charles Wood's CoffeeScript Basics and I have added what would be the equivalent PHP to hopefully give people a reference point.

CoffeeScript: Comment
#this is a comment

PHP
//this is a comment

CoffeeScript: Function
intro = (name)->
    "Hi " + name

Console.log intro("Brian")
The last line in a coffeescript function is returned

PHP
function intro($name){
return 'Hi'.$name;
}

echo intro('Brian');



CoffeeScript: Default Parameter
intro = (name, gender = "friend")->
    "Hi " + name + " my " + gender 

Console.log intro("Brian")

PHP
function intro($name, $gender  = 'friend'){
return 'Hi'.$name.' my '.$gender ;}

echo intro('Brian');


CoffeeScript: Modify A Argument's Value
intro = (name, gender = "friend")->
    gender = gender +"!";
    "Hi " + name + " my " + gender 

Console.log intro("Brian")

PHP
function intro($name, $gender  = 'friend'){
$gender  .= '!';
return 'Hi'.$name.' my '.$gender ;
}

echo intro('Brian');


CoffeeScript: String Interpolation
myScore = 6

console.log "my score was #{myScore}"


PHP
$myScore = 6;

echo "my score was $myScore"



CoffeeScript: Chained Comparisons
myScore = 6

pass = 10 > myScore > 5


PHP
$myScore = 6;

$pass = 10 > $myScore ? $myScore > 5 : false;



CoffeeScript: Hash Map
items = {a:'z', b:'y', c:'x'}

PHP
$items = ['a'=>'z', 'b'=>'y', 'c'=>'x'];


CoffeeScript: Array
items = [
    1,0,0
    0,1,0
    0,0,1
]
CoffeeScript will automatically add a comma at the end of each line in an array is not present

PHP
$items = [   
   1,0,0,
   0,1,0,
   0,0,1
];


CoffeeScript: If
x = true
y = false

if x and y
    console.log true
else
    console.log false

PHP
$x = true
$y = false

if( $x and $y)
    echo 'true';
else
    echo 'false';
Here the example of using endif
if( $x and $y):
    echo 'true';
else:
    echo 'false';
endif


CoffeeScript: Ternary Operator
if x or y then console.log true else console.log false
coffee supports and, or
PHP

echo $x or $y ? 'true' : 'false'


CoffeeScript: Not With Assignment
x = null
x or= true
      

PHP
$x = null;
$x = !$x ? true : $x;
      
for this, the ternary operator must have an else. So i'm using it's own value to simulat no effect.


CoffeeScript: Splats(Function Overloading)
party = (first, second, rest...) ->
      console.log first
      console.log second
      console.log rest
      

PHP
function party(first, second){
      echo $first;
      echo $second;
      $rest = func_get_args();
      array_shift($rest);//remove first
      array_shift($rest);//remove second
      echo implode(',',$rest);
}
      
You don't need implode, I'm just using it to print the exter value from this array.


CoffeeScript: For In/Each
hello = {en: "hi", fr:"Boj", it,"bon"}
speak = (lang) ->
      console.log hello[lang]
speak language for language in ["en","fr","it"]
      

PHP
$hello = ['en'=>'hi', 'fr'=>'Boj', 'it'=>'bon'];
function speak($lang){
      global $hello;
      echo $hello[$lang];
}
      foreach(['en','fr','it'] as $language) speak($language);
      


CoffeeScript: Sequence
countdown = (num for num in [10..1])
countdown = (num*2 for num in [10..1])
      

PHP
$countdown = range(10,1)
$countdown = range(10, 1, 2)
      


CoffeeScript: Parsing An Array
ages = {chuck:31, steven:29, julie:27}
tell = for person, age of ages
person + " is "+age+" years old"
      

PHP
$ages = ['chuck' => 31, 'steven' => 29, 'julie' => 27];
      foreach($ages as $person=> $age) 
      $tell[] = $person.' is '.$age.' years old';
      


CoffeeScript: Class
class Vehicle
      move: (miles) ->
            console.log miles+"miles"
car = new Vehicle
car.move(1000)
      

PHP
class Vehicle{
      public function move($_miles){
            echo $_miles.' miles';
      }
}
      $car = new Vehicle();
      $car->move(1000);
      


CoffeeScript: Attributes
class Vehicle
      setMiles: (@miles)
      getMiles: -> @miles 
car = new Vehicle
car.setMiles(1000)
console.log car.getMiles
      

PHP
class Vehicle{
      public $miles
      public function setMiles($_miles){
            $this->miles = $_miles;
      }
      public function getMiles(){
            return $this->miles;
      }
}
$car = new Vehicle();
$car->setMiles(1000);
echo $car->getMiles();
      


CoffeeScript: Inheritance
class Vehicle
      constructor: (@name) ->
      move: (miles) ->
            console.log @name + " drove "+miles+"miles"

class VWBug extends Vehicle
      move: ->
            console.log "fast"
            super 100

class Truck extends Vehicle
      move: ->
            console.log "slow"
            super 20

mater = new Truck "Mater"
her = new VWBug "Herbie"
mater.move()
her.move()
      

PHP
class Vehicle{
      private $name;
      public function __constructor($_name){
      $this->name = $_name;
      }
      public function move($_miles){
      echo $this->name.' dove '.$_miles.' miles';
      }
      }
      class VWBug extends  Vehicle {
      public function move($_miles = 100){
      echo 'fast';
      parent::move($_miles);
      }
      }
      class Truck extends  Vehicle{
      public function move($_miles = 50){
      echo 'slow';
      parent::move($_miles);
      }
      }
      $mater = new Truck("Mater");
      $her = new VWBug("Herbie");
      $mater->move();
      $her->move();
      
... continue reading!

Saturday, 25 May 2013

Cross-Domain Ajax with CoffeeScript

Ajax! The workhorse technology, that underpins our Web 2.0 world. Normally is something that we take for granted as web developers.
Except when you're trying to develop something in a small group and it just won't behave!!

Ok, context: I was building the front end to a site and a colleague was working on the back. The big problem came when I was trying to get json data from his service.. on his machine. You get where this is going :p

Error jQueryXXXXXXXX was not called

Solution?!

Jsonp. (WTF!) 'Jsonp' stands for "JSON with padding". But in a nutshell 'Jsonp' is requesting your json data from a dynamically created element on the page.
 *I'm still lost!!*
In order to keep your data secure when visiting web sites. The elders of the Internet decided that cross domain scripting would be a bad idea. This means that your browser restricts javascript to only send/receiving data to the domain that the page is coming from.

The workaround(Hack) is to dynamically create a hidden element on the page that points to the domain that you want to get your information from. The request goes out and the respond as javascript. [Don't worry. If you are using jQuery 1.5(or higher) this is all handled for you by using the the 'jsonp' data type in the jQuery ajax request]

So there are two parts to this.
A Server bit and a Browser bit.
*The Server bit is important!!*

On the Browser we need to send the ajax and have a function to process the response.

opets = 
 type: 'GET'
 url: 'http://192.168.1.117/myService/get.json'
 dataType: 'jsonp'
 async: false
 crossDomain: true
 jsonpCallback: 'callMe'
 error: (jqXHR, textStatus, errorThrown) ->
  alert "AJAX Error: #{textStatus}"

$.ajax opets


window.callMe = (data) ->
 console.log data

Server side. When using JSONP you should set the content-type to javascript(insted on "json").. as the respoince will be wrapped in your callback function

if(isset($_GET['callback'])){
 header('Content-Type: application/javascript');
 echo $_GET['callback'].'('.$jsonData.')';
}
... continue reading!

Saturday, 4 May 2013

Long polling

As some people seem to be having a tough time understanding this reverse ajax I decided to try and explain. so long polling or reverse ajax as its otherwise known. Is when you simulate the server informing you of changes, instead of constantly pulling the server for updates. 

*but Brian why is it a bad thing to constantly poll the server??

Polling the server is very expensive as a new connection needs to be created & handled on each request. Combine this with a lot of users and short polling time and your server can get quickly overloaded.

Here's an example of a normal ajax request to poll for updates.

normal ajax

  --------            --------
  | Base |            | Ship |
  --------            --------
      |                  |
      |  Every thing ok? |
      | ---------------->|>
      |                  | checking.. yep, all ok
     <|<---------------- |<
Lets  |                  |
wait  |                  |
a sec |                  |
     >| ---------------->|>
      |                  |Let check again
     <|<---------------- |<
      |                  |

What we are doing here is allowing the client to send request to see if anything has changed, then what I short while and the client will request again.


Long polling

This approach is best when you are checking for changes on a somewhat infrequent basis.

Here we change the architectural little bit. we take the request from the client.. but if there is nothing to return, we will hold the connection open.

  --------            --------
  | Base |            | Ship |
  --------            --------
      |                  |
      |  Everything ok?  |
     >| ---------------->|>
      |                  | checking.. no change
      |                  | (..Wait..)
      |                  | checking.. no change
      |                  | (..Wait..)
      |                  | checking.. no change
     <|<---------------- |<
      |  Everything ok?  |
     >| ---------------->|>
      |                  | checking.. no change
      |                  | (..Wait..)
      |                  | checking.. There a problem!!
 !!! <|<---------------- |<
      |                  |
      |                  |
      |                  |
      |                  |

This approach allows us to better manage connections as each client will have one connection that can be used over a longer time. If something happens with connection the good thing is the network layer will inform you and then you can just reconnect.

I have found good approach is to run a loop on the server 30 times and sleep for 1 second each iteration. but your mileage may vary
... continue reading!