Archive: November, 2010

Type checking vs too much typing…

This had me pondering for a minute.

Quite often I write code along the lines of:

public function doStuff($stuff, $complex = FALSE) {
  if ($complex) {
      echo 'Doing complex stuff<br />';
  } else {
      echo 'Doing simple stuff<br />';
  }
}

Alrighty, this does not seem too bad.
If our default is $complex = FALSE, then we’ll always be doing “simple stuff”.

However, once the client (developer) accesses the method based on the given API … We could have a potential problem.

Let’s look at these scenarios:

$this->doStuff('some stuff'); //lazy developer, knows the API, doesn't bother with unnecessary argument
$this->doStuff('some stuff', FALSE); //proper developer, better be safe than sorry
$this->doStuff('some stuff', 'false'); //silly developer

As you can imagine in the first two cases we were “Doing simple stuff”… However because the third developer accidentally (or what have ya) enclosed the ‘false’ Boolean into a string PHP took care of type conversion and had to evaluate that string to meaning TRUE.

PHP’s fault? …. neah
Developer’s fault? …. neah (although some will argue that).
Lazy API developer? … most likely.

Let’s improve the method a little:

public function doStuff($stuff, $complex = FALSE) {
if (is_bool($complex) && $complex) {
     echo 'Doing complex stuff<br />';
  } else if (is_bool($complex) && !$complex) {
     echo 'Doing simple stuff<br />';
  } else {
     echo 'You have passed the wrong type, silly<br />';
  }
}

More, but safer code. Just wanted to point this out. Pick your own battles.

Show git branch in your bash prompt

Quite a convenient little snippet. Thought I would share it with all my dear readers and git lovers.

(Thanks to the original author, whom I cannot remember right now. I’ll gladly post the link to the original source if someone reminds me)

Add the snippet below to your .bash_profile
(Don’t forget to “source” the file if need be).

And now your bash will look something like:
$ /usr/home/teknoid/some-git-project(master)

Where, “(master)” is of course the git branch name you are currently working with. (Hey, picking of colors is up to you ;))

Enjoy.

#showing git branches in bash prompt
function parse_git_branch {
  git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}

function proml {
  local         RED=&quot;\[&#92;&#48;33[0;31m\]&quot;
  local   LIGHT_RED=&quot;\[&#92;&#48;33[1;31m\]&quot;
  local      YELLOW=&quot;\[&#92;&#48;33[0;33m\]&quot;
  local LIGHT_GREEN=&quot;\[&#92;&#48;33[1;32m\]&quot;
  local       WHITE=&quot;\[&#92;&#48;33[1;37m\]&quot;
  local  LIGHT_GRAY=&quot;\[&#92;&#48;33[0;37m\]&quot;
  local LIGHT_PURPLE=&quot;\[&#92;&#48;33[1;34m\]&quot;
  case $TERM in
    xterm*)
    TITLEBAR='\[&#92;&#48;33]0;\u@\h:\w&#92;&#48;07\]'
    ;;
    *)
    TITLEBAR=&quot;&quot;
    ;;
  esac

PS1=&quot;${TITLEBAR}\
$LIGHT_PURPLE\w$YELLOW\$(parse_git_branch)\
\n$LIGHT_GRAY\$ &quot;
PS2='> '
PS4='+ '
}
proml

Helpful jQuery modals

This post is actually mostly about jQuery (with some cake sprinkles), but why not…

Let’s examine a typical situation:

We have a Product model, which belongsTo a Category model.

Now we need to add some products…

An admin interface would have a category select input (or drop-down) and a few form fields to fill-in some product details. Happily, we venture to add our first product, only to realize that we have not yet created any categories… backtracking to create a category would be a shame and with a little help from jQuery we can easily solve this problem.

One state that developers rarely consider during (and after) development, is the “blank” state of the application, which in turn can lead to some unexpected behavior…

The goal is to do the following:

  1. Get to the www.example.com/products/add page
  2. Using jQuery, “realize” that our Category drop-down is empty
  3. Prompt the user through… “lightwindow-modal-jquery-ui-dialog”… To create at least one category, so we could get moving
  4. Refresh the product/add page with the newly created category neatly in place within the select input

Since I use jQuery extensively, I am going to pick jQuery UI’s dialog widget to accomplish my needs. (It may not be the most robust or feature-rich, but it plays nice with the jQuery core… and does what I need).

(It goes without saying that you should include jQuery core and jQuery UI libraries… load them from Google, if you’d like).

Anyway…
First, let’s take a look at the products/add view:

<?php $this->Html->script('jquery.form.js', array('inline' => FALSE)); ?>
<?php $this->Html->script('parent_list.js', array('inline' => FALSE)); ?>
<?php $this->Html->css(array('smoothness/jquery'), NULL, array('inline' => FALSE)); ?>

<div>
  <?php
    echo $this->Form->create('Product');
    echo $this->Form->input('category_id', array('class' => 'parent-list'));
    echo $this->Form->input('name');
    echo $this->Form->end('Add product');
  ?>
</div>

<div id=&quot;category-form&quot;>
  <?php
    echo $this->Form->create('Category', array('action' => 'add'));
    echo $this->Form->input('name');
    echo $this->Form->end('Create category');
  ?>
</div>

Stepping through the code, the first thing we see is the jquery.form plugin. This will be used for submitting the “category add” form via AJAX, from the modal. (Will show that later on).
Next, we load parent_list.js, which is going to handle most of the magic.
Finally, in the view we have a div category-form (which will be turned by jQuery UI into a dialog/modal).

As you can see both forms are very simple, for purpose of this example.

Now, let’s see the jQuery file, which does all the heavy lifting:

[javascript]
(function ($) {
var getModal = function () {
$(‘#category-form’).dialog({
modal: true,
autoOpen: false,
title: ‘Create a category’
});

if($(‘.parent-list’).children().size() === 0) {
$(‘#category-form’).dialog(‘open’);
}
};

var showResponse = function (response) {
if(response == ‘saved’) {
$(‘#category-form’).dialog(‘close’);
window.location.reload();
}
};

$(document).ready(function() {
getModal();

var submitOptions = {
success: showResponse,
dataType: ‘json’
};

$(‘#CategoryAddForm’).ajaxForm(submitOptions);
});
}(jQuery));
[/javascript]

This is more JavaScript/jQuery than I usually show, so let’s take a look at some interesting things.
First, you’ll notice that the entire code is wrapped into a “self-calling anonymous function”. To keep things simple, the two benefits of using such pattern is to avoid conflicts and global vars (although it is not evident from this example, but a little googlin’ will explain things in more detail).

Next, notice the function declarations: var getModal = function () … by using such assignment we avoid a couple of problems in everybody’s favorite IE (the above method will define the function at parse-time, rather than run-time). It also kind of “forces” the developer to declare and call things in proper sequence without hoping that the browser might pick up some of the slack, where developer was careless. At any rate, run your JavaScript through JSLint before going to production ;)

Now that the general stuff is out of the way, let’s see the “most important” line of code:
if($(‘.parent-list’).children().size() === 0)
The above will check the category select input (i.e. parent of the product) to see if it has any options (options are children of the category select in this case). If not, the jQuery goodness kicks in and we get a modal/dialog which displays the category add form, as you saw from the products/add view above.

Once the name is entered and submitted via AJAX, I send back “saved” from the server as a response (assuming that all goes well). At which point we close the dialog and refresh the page. Now, we have our newly added category as one of the options… and can continue to add the product without backtracking to create a category in some other UI.

Hopefully this serves as a decent example on how to build a much more intelligent UI and improve user experience, with the help from the lovely jQuery and CakePHP.

Very hacky way to get client’s country code based on IP

You’d think that by now there should be an easier way to accomplish something like this.
(i.e. Send a client IP to some service, and get their country or other location information).

All my research just pointed to some some API’s, complicated components and way to much extra leg work to achieve something seemingly simple.

Note, I need to take care of this on the server side, thus I couldn’t fully leverage google’s JSAPI.

Yet, I could do the following:

public function getClientCountry() {
    App::import('Core', 'HttpSocket');
    $HttpSocket = new HttpSocket();
    $response = preg_split('/&quot;country_code&quot;:&quot;/', $HttpSocket->get('http://www.google.com/jsapi?'));
    return substr($response[1], 0, 2);
  }

Simply load the above URL in your browser to see the actual response…
Once I get the full response back, I hack my way to “extract” the value. Blah.

p.s. If someone has better alternatives, please share. Thanks ;)