Tuesday, December 18, 2012

CakePHP: Save and Show

In this small code snippet I show how to store some formulary data corresponding to an ad, and after saving redirect to the page to show the stored values.
<?php

//...

class AdsController extends AppController {
  
 public function add() {  
        if ($this->request->is('post')) {
         if ($this->Ad->save($this->request->data)) {
              $this->Session->setFlash('The ad was saved!');
              $inserted_id = $this->Ad->id;              
              $this->redirect(array('action' => 'view', $inserted_id ));
         } else {
             $this->Session->setFlash('The ad could not be saved!');
         }
  }
  // ...
    }
    
 // ...
 
 public function view($id) {
        $this->Ad->id = $id;
        $this->set('ad', $this->Ad->read());
    }    
}
The key line is the redirect. It took me a while to figure out how could I pass the just inserted id to the view page.

Friday, November 23, 2012

Android: Checking WiFi Connection

To be able to check WiFi connection in an Android application you first need to set the proper permission in the Android manifest:


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mytoolbox"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="15" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
 ...
 
</manifest>

Here's a code to check the WiFi. If it's not on it shows an alert message indicating connection is required and then it finishes the application:



private void checkWiFiConnectivity() {
  ConnectivityManager connMan =  (ConnectivityManager) 
       getSystemService(Context.CONNECTIVITY_SERVICE);
  boolean wifiIsOn = connMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
        .isConnectedOrConnecting();
  Log.d("GABO", "WiFi is : " + wifiIsOn);
  
  if(!wifiIsOn) {
   finishApplication();
  }  
}

private void finishApplication() {
  AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
  builder.setMessage("You need WiFi connection to access this App!");
  builder.setCancelable(false);
     
  builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
   
   @Override
   public void onClick(DialogInterface dialog, int which) {
       MainActivity.this.finish();    
   }
  });
     
  AlertDialog alert = builder.create();
  alert.show();  
}

Thursday, November 22, 2012

JavaScript: Copy & Highlight


As part of my discipline for documenting those functionalities that make me suffer and sweat, I want to leave this short code exemplifying how to make a copy & paste of an element of the DOM, at the same time that it highlights the element.

For the copy part I used a popular library that uses a Flash file as the executor of the operation: ZeroClipboard. The copy operation is not a standard capability of all browsers. That's whay a Flash file is requried. For the highlighting I found a code that works properly in the main browsers (IE, FF, Safari & Chrome). These are the  functions in the below code: "getTextNodesIn" and "setSelectionRange". The entire code below allows the user to click in the text for automatically make a copy to the clipboard, and then show copied text as an alert message. At the end it highlights the text.


<html>
<head>
<script type="text/javascript" src="ZeroClipboard.min.js"></script>  
<script type="text/javascript">
 function getTextNodesIn(node) {
  var textNodes = [];
  if (node.nodeType == 3) {
   textNodes.push(node);
  } else {
   var children = node.childNodes;
   for (var i = 0, len = children.length; i < len; ++i) {
    textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
   }
  }
  return textNodes;
 }

 function setSelectionRange(el, start, end) {
  if (document.createRange && window.getSelection) {
   var range = document.createRange();
   range.selectNodeContents(el);
   var textNodes = getTextNodesIn(el);
   var foundStart = false;
   var charCount = 0, endCharCount;

   for (var i = 0, textNode; textNode = textNodes[i++]; ) {
    endCharCount = charCount + textNode.length;
    if (!foundStart && start >= charCount
      && (start < endCharCount ||
      (start == endCharCount && i < textNodes.length))) {
     range.setStart(textNode, start - charCount);
     foundStart = true;
    }
    if (foundStart && end <= endCharCount) {
     range.setEnd(textNode, end - charCount);
     break;
    }
    charCount = endCharCount;
   }

   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
  } else if (document.selection && document.body.createTextRange) {
   var textRange = document.body.createTextRange();
   textRange.moveToElementText(el);
   textRange.collapse(true);
   textRange.moveEnd("character", end);
   textRange.moveStart("character", start);
   textRange.select();
  }
 }

 function highlight() {
  var element = document.getElementById("span_id");
  setSelectionRange(element, 0, element.innerHTML.length); 
  alert("copied!");
 }

</script>
</head>
<body>
 <span id="span_id">Copy Me!</span>
 <script>
  ZeroClipboard.setMoviePath( 'ZeroClipboard.swf' );
  var clip = new ZeroClipboard.Client();
  var element = document.getElementById("span_id");
  clip.setText( element.innerHTML )
  clip.glue( 'span_id' ); 
  clip.addEventListener( 'onMouseUp', highlight );
 </script>
</html>
</body>


Sunday, November 18, 2012

MongoDB under its proper context


A couple of weeks ago I attended to a CRJUG speak organized by the folks of BodyBuilding.com. In this time they gave us an introduction to the world of MongoDB, a non-sql database engine that they use in their site. I really enjoyed the loose style of the speakers. A “For programmers-by-programmers” approach. They showed us the differences of this paradigm with the traditional relational paradigm. I think they were very transparent from the beginning stating that they didn’t come in an “evangelistic mission”. They know as many do that this approach serves specific purposes. It doesn’t substitute the secure, transaction-safe, full referential integrity relational databases. Like in many things in computer science where there is this constant battle to try to balance all key aspects of a system: security, robustness, speed, etc, databases as well do not escape from this challenge.

I’m emphasizing this point for something that I found interesting during the presentation. Since there was openness at all time for questions and comments, some participants in various occasions insisted in compare this solution with standard relational database, which in principle it’s fine to point out why it’s done differently, but what I find interesting is that I detected some sort of skepticism while discussing the topics, like “I cannot believe the standard rules are being broken”. This was not said literally, I’m just describing my perception from their feedback. For example one participant commented that Oracle has some ways to attack similar problems. In other occasion there was brief argumentation of why MongoDB didn’t continue with a typical SQL language instead of using a very different query language, because after all, it would be easier for the entire developer’s community who already know SQL.

This is interesting, but not surprising. Relational  databases had been with us for more than 40 years. They are older than a lot of us. That’s why a lot of people find it a little difficult to believe that a new approach is required. Maybe it’s similar like if there was new programming language selling the idea that OOP should be dismissed. In my humble opinion I believe new paradigms experimentation is always required in order for innovation to appear. I also think we don’t have drive ourselves in a “Hispster” fashion, looking for the newest technologies and then labeling the other ones as the old fashion ones. Relational databases are too long to be entering the retiring cycle, but still we need to start considering the new guys entering the scene.

In this very funny video we see this point shown, where many people are too fast in dismissing the old technologies without having solid argumentation; just playing hipster with technology. I don’t think the video is a criticism to MongoDB, but a criticism to people who do not know the proper context of certain technologies. If you have a small start-up, you should not be worrying in the short term about scaling and use a non-sql database. Over architecting an application can cause more problems than it solves. But that’s another discussion I would like also to write about it in another moment.


Wednesday, November 7, 2012

Simple code for finding missing alphabet letters in a sentence

I consider no code is trash even if it's too trivial. And I also hate the sensation of knowing I code something similar before, but have to repeat the coding because I didn't save it. Some time ago I had to code a solution for a simple problem as part of the recruiting process in a company. The problem to solve is to find the missing letters of the alphabet in a given sentence.


import java.util.HashSet;
import java.util.Set;
 
/**
* Test code to find missing letters of the alphabet from a String sentence.
* @author gabriel.solano
*
*/
public class MissingLetters {
 
private final int ASCII_CODE_FOR_LETTER_A = 97;
private final int ASCII_CODE_FOR_LETTER_Z = 122;
 
/**
* Gets the missing letters of a sentence in lower case.
* @param sentence
* @return String having all the letters that the sentence is missing from the alphabet.
*/
public String getMissingLetters(String sentence){
/*
 * 1. Let's populate a set with the unique characters of the sentence.
 *    This approach avoids having two nested for's in the code (better performance).
 */
Set<Integer> uniqueASCIICodes = new HashSet<Integer>();
 
for (char character : sentence.toLowerCase().toCharArray() ) {
 if (character >= ASCII_CODE_FOR_LETTER_A
   && character <= ASCII_CODE_FOR_LETTER_Z) { // Range of lower case letters.
  uniqueASCIICodes.add((int)character);
 
  if (uniqueASCIICodes.size() == 26) {
   break; // Sentence already covered all letter from the alphabet.
  }
 }
}
/*
 * 2. Move in the range of ascii codes of lower case alphabet
 * and check if letter was present in sentence.
 */
StringBuilder misingLettersBuilder = new StringBuilder();
 
for (int i=ASCII_CODE_FOR_LETTER_A; i <= ASCII_CODE_FOR_LETTER_Z; i++) {
 if (!uniqueASCIICodes.contains(i)) {
  misingLettersBuilder.append((char)i);
 }
}
   return misingLettersBuilder.toString();
}
 
public static void main(String[] args) {

   String case1 = "A quick brown fox jumps over the lazy dog";
   String case2 = "bjkmqz";
   String case3 = "cfjkpquvwxz";
   String case4 = "";
 
   MissingLetters missingLetters = new MissingLetters();
 
  System.out.println("Missing letters for[" + case1 + "]: " +
  missingLetters.getMissingLetters(case1));
  System.out.println("Missing letters for[" + case2 + "]: " +
  missingLetters.getMissingLetters(case2));
  System.out.println("Missing letters for[" + case3 + "]: " +
  missingLetters.getMissingLetters(case3));
  System.out.println("Missing letters for[" + case4 + "]: " +
  missingLetters.getMissingLetters(case4));
   }
}
This will be the program output:
Missing letters for[A quick brown fox jumps over the lazy dog]: 
Missing letters for[bjkmqz]: acdefghilnoprstuvwxy
Missing letters for[cfjkpquvwxz]: abdeghilmnorsty
Missing letters for[]: abcdefghijklmnopqrstuvwxyz