Thursday 29 December 2011

Datatype support for MongoModel

Mongomodel is a ruby gem that does the Data mapping for mongo db. It supports the most commonly used data types. Recently our team had a requirement to handle (persist and retrieve back data from mongodb) OpenStruct. Since the mongomodel documentation doesn't provide enough information on how to extend it to support a new datatype, we tried to give it a shot ourselves and to our surprise it was much easier and straight forward than what we thought.

All that mongomodel expects is to have a class (converter) that can serialize and deserialize the datatype to be persisted in the mongodb. So, we'll start by defining the class with 'from_mongo' and 'to_mongo' methods in it.

module MongoModel
   module Types
      class MongoOpenStruct
         def from_mongo(value)
            OpenStruct.new(value)
         end
         def to_mongo(value)
            value.marshal_dump
         end
      end
   end
end

Alright. Now we need to tell mongo to use this class if it comes across a OpenStruct property in any mongomodel document. Mongomodel uses an internal hash map to identify the converter for a given datatype. So, all that we need to do is to add an entry (just after the 'converter' class defnition) for OpenStruct in the mapping.

Types::CONVERTER.merge! ::OpenStruct => Types::MongoOpenStruct.new

Thats it! We can now start using OpenStruct properties in any mongomodel document.

class Article < MongoModel::Document
   property :some_property, OpenStruct
end

Friday 4 November 2011

Integration testing Search - Clash of the indices


ElasticSearch is an Open Source (Apache 2), Distributed, RESTful, Search Engine built on top of Apache Lucene. It promises to solve all the pain points of implementing search in a web application. Tire is one of the popular ruby clients for elasticsearch. Though it is important to have integration test for models while using tire in a ruby app, it is equally important to make sure that the test doesn't corrupt the development indices.

One approach to overcome this is to create a dummy class in the test that includes the Tire::Model::Search and Tire::Model::Callbacks module and use it to create indices and test search in the integration test. While this seems simple, there is a cleaner approach, that lets us use the actual models in test and does not corrupt the development indices as well. There is a configuration in tire that lets you provide the prefix to the index name. By specifying the
Tire::Model::Search.index_prefix Rails.env
in the initializers/tire.rb file, we can tell tire to use different indices for different environments. For example, the search in the dev mode will use "development_model_name" index and that in the test environment will use "test_model_name" index.

Monday 27 June 2011

Monkey see, Monkey do - Why can't we?

Empathy - The ability to understand and share the feelings of another person - is one quality that we have been taught to have since childhood. I'm sure everyone of us would have felt the emotions, that the presence or absence of empathy, brings to us. I was under the impression that empathy or putting oneself into the other person's shoes or being on the other side of the table or whatever you call it, is a skill that every human being should try and develop, till I started reading "Just Listen" by Mark Goulston. It was interesting to know that it is not a skill that a person develops but instead it is wired in his brain. In fact that is something that we inherited from our ancestors during the evolution.

It has been proved by scientists who studied specific nerve cells of macaque monkeys that, these monkeys' brain cells reacted in the same way when the monkey performed some action and when it watched some other monkey perform the same action. V.S.Ramachandran explained in his ted talk that if we could remove the skin cells that senses the touch and sends the signals to brain, the reactions in the brain would be the same, if we were touched or if we watch someone else being touched. To the brain, it is all the same.

Every human being has this ability to empathize another person and expects the world to reflect our feelings as well (at least a little). Or in Mark's words
Each time we mirror the world, it creates a little reciprocal hunger to be mirrored back.
But most of the time we fail to do just that and it might create an impact in the other person called "mirror neuron receptor deficit".  When people experience it, they feel that they are left alone and depressed. Most of the techniques, to get through people,explained in this book is just about making people feel felt. When we mirror people's feelings/emotions it makes them feel less alone, which brings some relief to them, which in turn makes them feel more relaxed. As a result they'll be more open to listen to us and willing to work with us. I believe that this simple science must be very useful and handy to everyone of us who need to collaborate with a bunch of people day in and day out.

Saturday 4 June 2011

The road to ThoughtWorks

One fine evening in the first month of my final year in college, we got an information from my placement officer that a company called ThoughtWorks (TW) is visiting our campus. None of us got the name right in first place. He spelled it out for us and we googled to find out more about TW. The day before TW was supposed to come to my college, I received a call from one of my lecturers. He asked all the placement reps (I was one of them) to come early that day. I had no clue as to why he called for a meeting but still, being an early bird I showed up early, while none of the others turned up.

The first round of placement was just over, by that time, and there were still some students left in my department who were not placed yet. He started off with asking me the stats and then went on to blast me for not taking any step towards getting those students placed. I tried to explain him on whats going on, but I stopped responding when i realized that he was not ready to listen and started comparing us with the rest of the placement reps in other departments. I was super pissed off. He went on for more than two hours and then calmed down and wished me good luck for ThoughtWorks. I left the room with no motivation to do anything.

In the afternoon we went to attend the pre placement talk, just for the sake of attending it. Initially I was thinking that its gonna be yet another ppt. But i was proved wrong. It was amazing I should say. They took us through the everyday life of an TWer and i was pretty impressed. I was all excited about getting this company. Then came a slide in the presentation that listed the languages and platforms TW works with.  I have written Java programs (as simple as to find the inet address of the machine) in the networking lab. That is all the Java knowledge I had. I've heard of .Net, but didn't have a clue about what Ruby and Perl are about. The question "Will I make it?" was lingering in my mind, but still I wanted to give it a try.

The first round was logical. But the kind of questions were different and interesting. I enjoyed solving those and successfully cleared that. Then came the pairing round. We were given two problem statements. We had to provide a solution to the problem of our choice in the language of our preference. That was really simple for me. I chose a problem that I understood and decided to code it in C, since it was the only language that I was comfortable with at that time. I had no other choice. The most impressive thing about this round was the freedom that we were given to refer to any book of our choice and use internet. Never heard about anything of that sort in any of the recruitment process. While we were coding, people from TW were pairing with us, helping us and assessing us in the mean time. The coding round was over and then came the interview.

The interview started with my self introduction, the only thing that we've been rehearsing for the last one year in all of the pre placement trainings. The interview went on for about 45 mins. After that we were anxiously waiting for the recruitment team to comeback with the results. They called me in first. I walked in thinking that all the rounds were over and getting the offer was the only thing left. Well. Not so soon. I had a wonderlic test to clear. I didn't know how the twelve minutes passed. But in the end it was all for good. I cleared it and received the offer and a bunch of goodies from ThoughtWorks. I was all smiles when I came out, so nobody had to ask me if I was placed. That was the moment I cherished.

It's been three years now, since I joined ThoughtWorks. But this experience has been refreshing and brings me goosebumps every time I think about it.

Saturday 28 May 2011

Android vs WP7

After a short stint in android development, I thought of experimenting with a different mobile platform. I didn't have too many options. iPhone development was ruled out since i did not have a mac and wasn't quite comfortable with Objective C. I chose WP7, hoping to catch up with C# coding which I haven't been doing for a looong time. And moreover the latest buzz about the next version of windows phone, Mango added up to the excitement to see what it offers to the developers. I made up my mind and setup the environment  and started off with a simple BMI calculator application for WP7 and android. Here is the summary of stuff that I discovered last week.

                   Android                      Windows Phone 7
The multiple screen sizes are handled by android itself. The developer is concerned with following the best practices to support this. Though only two screen sizes are possible, you need to code differently for them. Even conditional statemenst in code and different xaml files might be required to cater different screen sizes.
The template editor is still basic. Throws up exceptions when background of an element is set to an xml. Needs a lot of improvement in this area. Has a very decent template editor - more similar to what we've seen and used to design the template for VB and C# windows applications. It is very dynamic and responsive to changes in xaml file and vice versa.
Though you'll find some surprises its easy to draw analogy from web development. Silverlight is used for development. Requires too much of code to achieve even the simplest functionality.
Takes a good amount of time to setup the eclipse plugin and android SDK. But once setup development and testing in emulator is much faster than WP7 Setting up the environment takes more than three hours and the tools are pretty slow if you are developing and testing it in the emulator frequently.
Costs only $25 to register as an android developer and start publishing. To publish an app in the marketplace, you need to pay an annual subscription fee of $99

The source code for android and windows phone are available in github.

Friday 6 May 2011

Ruby - Gems - Manage dependencies

Had a chance to work on a Ruby on Rails project recently. It is almost impossible to have a ruby application without using any gems. Gem is a packeged ruby application or library which can be used in other applications (equivalent to a jar in a java project). You can specify the gem dependencies for your application in the Gemfile. The bundler takes care of resolving the gem dependencies of the application for you. It makes sure that the same version of gems are used in all the machines/environments wherever you develop/deploy the application.

Still, you could run into the problem of nested dependencies not being resolved, as I did. My application was dependent on a gem (say Gem-A), which was dependent on another gem (say Gem-B). You'll naturally expect the bundler to resolve this and install Gem-B for your app. But the bundler failed to resolve this in my case.

Let's take a small peek into how gems are built. Gems are ruby projects in themselves. In case of  a gem, you have another place (apart from the Gemfile) where its gem dependencies should be specified. Enter the gemspec file. The gemspec file contains the specification of the gem, like the name, version, authors. A sample gemspec file would look like this:

Gem::Specification.new do |s|
  s.name = 'my_gem'
  s.version = '1.0.0'
  s.authors = ["Me", "Myself"]
.
.
.
  s.add_runtime_dependency 'activesupport', '~> 3.0'
  s.add_development_dependency 'rails', '~> 3.0'
  s.add_development_dependency 'rspec', '~> 2.0'
  s.add_development_dependency 'rake'
  s.add_development_dependency 'sqlite3'
end

If any application is dependent on 'my_gem', the bundler will look at the runtime dependencies from the my_gem.gemspec file and it'll install the 'activesupport' gem as well, since it is a nested dependency.

Coming back to the problem in hand, the root cause was in the way Gem-A has specified its dependencies. It has added Gem-B as a dependency in its Gemfile, but hasn't specified it as a runtime dependency in its gemspec file and hence the bundler cannot identify Gem-B as a dependency. To resolve this, I had to add Gem-B as a dependency to my application as well.

It is a good practice to specify your runtime and development dependencies in gemspec and include it in your Gemfile, while developing gems. Your Gemfile will look something like:

source 'http://rubygems.org'
gemspec
gem 'ruby-debug', :platform => :ruby_18
gem 'ruby-debug19', :platform => :ruby_19

This will save a lot of time for the developers who use your gem.

Monday 11 April 2011

Model form - Get it working

Started playing around with python and django last week. There is a lot of stuff that django provides us to build a basic web app. Despite its very good documentation, I found it hard to get the model form working. Model forms are useful when you have a basic model with some fields defined and you need a form to either add or edit the model. Writing views for such models is redundant, since both of them are going to contain the same information anyway and its prone to human error. Model form comes in handy in such situations.

Lets get started with a basic model that holds an item, its price and the date when it was added:

from django.db import models

class Transaction(models.Model):
item = models.CharField(max_length=200)
price = models.IntegerField()
date_added = models.DateTimeField('date added')

A model form for the above would look like:

from django import forms

class TransactionForm(forms.ModelForm):
        class Meta:
                model = Transaction
        date_added = forms.DateField(initial=datetime.date.today)

To display the model form in a view, we need to have a html file that'll be used to render the model form that is passed as a parameter to that. Using django's shortcuts we can render the form using the code below:

def index(request):
        return render_to_response('managExpenses/transaction_form.html', {'form':TransactionForm}, context_instance=RequestContext(request))

If you are using django's generic views, then the code will look like:

def index(request):
        return create_object(request, form_class=TransactionForm)

In the above code, the create_object method will look for the transaction_form.html placed in the templates folder and use it to render the form.

The transaction_form.html looks something like:

<form action="/some/url/" method="post">
{% csrf_token %}
{{form}}
<input type="submit" value="Submit"/>
</form>

The model form is replaces the {{form}} in the above html. The csrf_token is used by the CSRF (Cross Site Request Forgery) protection and needs to be included in every form that posts to your internal url. 

You can now go ahead and modify the urls.py to assign a url pattern to the above view and see it working.

Friday 1 April 2011

Tamil in android

Displaying tamil characters in android can be easily achieved by using TSCII (Tamil Standard Code for Information Interchange) fonts. TSCII is an extended ASCII encoding standard. Unlike ASCII which uses 7 bits for encoding, TSCII makes use of all the 8 bits in a byte. The first 128 bytes remains the same as that of ASCII.  The tamil vowels and consonants along with the common prefixes, suffixes and other special characters fill up the rest of the 128 bytes.


You can place the TSCII font in the assets folder of your android application and set it to any view where you need to display tamil text.

Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/tscFont.ttf");
TextView textView = new TextView(context);
textView.setTypeface(tf);


If you have the text in unicode format, there are online tools available that can help you convert the tamil text from unicode to TSCII format and vice versa.