senthil's posterous http://senthilnambi.posterous.com Taking apart things & throwing them on the floor - sometimes setting them on fire to test flammability. posterous.com Wed, 07 Mar 2012 19:44:44 -0800 FbWrapper Part 1: Create a bare bones wrapper for Facebook Pages api http://senthilnambi.posterous.com/fbwrapper-part-1-create-a-bare-bones-wrapper-70748 http://senthilnambi.posterous.com/fbwrapper-part-1-create-a-bare-bones-wrapper-70748

Goals for Part 1

  1. All GET requests related to Pages, i.e. posts, comments, likes should work.
  2. All requests must parse json and return an FbWrapper object.
  3. Decouple the various parts.
  4. Full integration test suite.
  5. No abstraction or metaprogramming (that’s part 2).
  6. No third party libraries (using open-uri for connections and std lib json)

Preparation

  1. Watched Sandi Metz’s talk on Design.
  2. Took apart the excellent Twitter gem.

Desired Api

#! ruby
  config = FbWrapper::Config.new(:access_token = 'a_access_token')
  client = FbWrapper::Client.new(config)

  # directly calling on client
  client.get_page(page_id)
  client.get_posts(page_id)

  client.get_post(post_id)
  client.get_comments(post_id)
  client.get_likes(post_id)

  client.get_comment(comment_id)
  client.get_like(like_id)

  # call from individual nodes
  page  = client.get_page(page_id)
  posts = page.get_posts

  post  = posts.first

  comm  = post.get_comments
  like  = post.get_likes

Skeleton app

If you want to follow along: link. I used hero to create it.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Thu, 01 Mar 2012 17:18:00 -0800 On criticism http://senthilnambi.posterous.com/on-criticism http://senthilnambi.posterous.com/on-criticism

What this post is about:

  1. Different types of criticism   2. Why criticism?

There are many varieties of criticism (see wikipedia for full list), but today I’ll talk about just three:

  1. Theoretical   2. Anecdotal evidence   3. Personal preference

I, ofcourse, made up these names in the last 30 mins, and are probably wrong.

Different types of criticism

For good or bad, CoffeeScript invokes very strong opinions, much like Rails and therefore an excellent example to talk about criticism.

“I can’t shake the feeling that people that like CoffeeScript are those that don’t "get” JavaScript (e.g. CoffeeScript’s notion of a class, whereas JavaScript has none — let go an embrace the prototypal object model).“ Source 

The above is what I call a theoretical objection. It maybe true or false and frequently leads to insolvable debates, at least in the mind of a third party observer.

“The CoffeeScript Debugging Workflow

    First I have to find where the problem is in the JavaScript since it doesn’t compile line-for-line to my CoffeeScript.     Then I have to comprehend the JavaScript because it’s not my code.     After I comprehend the JavaScript I can work on discovering the problem.     Once I discover the problem I have to find the code in the CoffeeScript to fix it.     Fix it in the CoffeeScript.     Compile (usually automated, but still a step)     Problem fixed, move on, otherwise…     Wonder if the compile process was successful.     Go back to the JavaScript to see if it’s what I expect, start over."

Source

Ryan Florence has used coffeescript and above is his experience from using it. This is an example of anecdotal objection.

“Like Ruby and PERL, CoffeeScript violently violates what I consider the most important rule of Python: “There should be one — and preferably only one — obvious way to do it.” Source

This is a personal preference objection.

Why criticism?

If you were asked to make a decision on using coffeescript solely based on the three quotes above, which would you say helps you best make that choice? For me its the second one. While I don’t deny the role of the other two or question their truthiness, anecdotal evidence is someone’s real experience. Ofcourse, that experience might be false or not the same to everyone.

The best way often is to skip criticism all together and try it out, with an open mind, and then see if criticism matches our personal experience.

P.S. Personally I’ve very little opinion on CoffeeScript as a language. I included those quotes because I found them interesting, not to start yet another flame war.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Thu, 16 Feb 2012 11:56:51 -0800 Metaprogramming magic in Ruby http://senthilnambi.posterous.com/metaprogramming-magic-in-ruby-49038 http://senthilnambi.posterous.com/metaprogramming-magic-in-ruby-49038

The past week I’ve been playing with implementing LinkedList in Ruby, mainly Single and Double. Both of them include an Enumerable like module called Iteration. It provides methods like: each, count, map, select etc. Double also inclues IterationReverse which provides: reverse, map_reverse etc. As you can tell there’s a lot of code common between the two Iteration modules. The only real difference is each. Iteration#each starts at tail and iterates to head, while IterationReverse#each starts at head and iterates to tail. head being the first node added to list, while tail is last node added. (I know crappy class names right, we’ll fix it later). Late last night I started thinking about ways to DRY the two modules, this post is direct result of that.

First I renamed Iteration and IterationReverse to BackwardIteration and ForwardIteration. My original plan then was to extract out the common methods into Iteration, while implementing each in the respective modules.

module Iteration
  def map
  end
end

module ForwardIteration
  include Iteration

  def each
  end

module BackwardIteration
  include Iteration

  def each
  end
end

class SingleLinkedList
  include ForwardIteration
end

class DoubleLinkedList
  include ForwardIteration
  include BackwardIteration
end

The problem here is when you include BackwardIteration in DoubleLinkedList, it will override ForwardIteration#each.

Before we get any further, let’s write some specs. The below should be fairly self explanatory. We test #first which returns first added node, #last, first’s counterpart. #to_a iterates through list from head to tail, while #to_a_reverse, well you can guess. The last test was a regression test, which we’ll get to later.

describe 'LinkedList' do
  context SingleLinkedList do
    subject { described_class.new }

    it 'returns first character' do
      subject.first.should == 'F'
    end
  end

  context DoubleLinkedList do
    subject { described_class.new }

    it 'returns first character' do
      subject.first.should == 'F'
    end

    it 'returns last character' do
      subject.first_reverse.should == 'B'
    end

    it 'returns array from head to tail' do
      subject.to_a.should == %w(F o r w a r d)
    end

    it 'returns array from tail to head' do
      subject.to_a_reverse.should == %w(B a c k w a r d)
    end

    it 'does not override #each method' do
      subject.to_a_reverse.should == %w(B a c k w a r d)
      subject.to_a.should == %w(F o r w a r d)
    end
  end
end

What we need to do is to stop ForwardIteration#each from clashing with BackwardIteration#each, while also renaming the methods in BackwardIteration with _reverse added to them if ForwardIteration is defined.

First I tried to do this:

module BackwardIteration
  def self.included(base)
    if base.ancestors.include?(ForwardIteration)
      instance_methods.each do |method|
        base.class_eval do
          alias_method "#{method}_reverse", method

          define_method method do
            unbound = ForwardIteration.instance_method(method)
            unbound.bind(self).call
          end
        end
      end
    end
  end
end

What it does is it looks for ForwardIteration, if its defined, it changes its own method name, by adding _reverse to it. Then it forwards the method to point to ForwardIteration. Ruby lets you get a method as an object with #instance_method(method), you’ll have to bind the method to the object, i.e. put the method in the lookup chain, then you can call it. But it didn’t work as I thought it would, so I decided to try another way.

Below I use method_missing is catch methods with _reverse suffix. For those methods, I temporarily redefine each to point to BackwardIteration#each and then call the method. Once done, I redefine each to point to ForwardIteration#each.

module BackwardIteration
  include Iteration

  def method_missing(method, *args, &blk)
    if method.to_s =~ /^(.*)_reverse/
      define_each
      result = send($1.to_sym)
      undef_each

      result
    end
  end

  def define_each
    class << self
      define_method :each do
        e = BackwardIteration.instance_method(:each)
        e.bind(self).call
      end
    end
  end

  def undef_each
    class << self
      define_method :each do
        super()
      end
    end
  end

  def each
    'Backward'
  end
end

class DoubleLinkedList
  include ForwardIteration
  include BackwardIteration
end

Clearly the constant defining and redefining of each isn’t a very good idea, but this was just a learning experience and I had a whole lot of fun trying to get it to work. Hopefully the specs pass for you and you learned a little bit more about the dynamic nature of Ruby.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Mon, 13 Feb 2012 23:44:00 -0800 rSpec best practices http://senthilnambi.posterous.com/rspec-best-practices-41505 http://senthilnambi.posterous.com/rspec-best-practices-41505

Most of rSpec best practices are found here:

Here are some I learned while working on algorithms.

  1. Use symbolic constants whenever possible.

When you decide to change the name of something or rename your class, you don’t want to hunt down every occurance of it. This happens way more often in specs when using bdd.

let is great for that purpose.

let(:one_array) do
  ['one']
end
  1. Use subject

For the same reason above. You define it once, and use it through in your specs.

subject do
  list = described_class.new
  list << 'one'
  list
end

it 'returns size' do
  subject.size.should == 1
end
  1. Define subject explicityly.

rSpec is smart enough to detect it most of the time from describe, but you should define it anyway. Makes for easier reading.

  1. Use described_class

It refers to the argument passed in to describe. Again, same principle.

describe Algorithm::DoubleLinkedList do
  subject do
    described_class.new
  end
end
  1. Use context to organize specs related to a method

For the above project, I had three contexts based on the size of the list:

  • zero_nodes
  • one_node
  • multiple_nodes

But, I had to jump too much to find the related specs, so now they’re organized by methods instead. Now after adding/changing a method, I can just jump to the appropriate context and change the specs.

In the above project I probably reorganized the specs at least three times to make it easier to deal with the complexity. A good indicator about the health of your specs is how confident you feel changing something in the project. And also how much you dread having to work with the specs.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Tue, 24 Jan 2012 23:03:51 -0800 Customizing zshrc prompt to have git info in Ruby http://senthilnambi.posterous.com/post/16455889894 http://senthilnambi.posterous.com/post/16455889894

I’ve been using Gary B’s dotfiles ever since I saw his PeepCode screencast, especially like his zshrc prompt, which looks like:

bin(0min|master?) $

bin - folder name 0 min - time since last commit master - name of current branch ! - there untracked files in the repo.

Its pretty helpful since I use terminal a lot, but one problem is the speed when switching to new repos, especially ones not opened for a long time. I didn’t mind it that much, especially since I found no good alternatives, but after looking at PeepCode’s latest blog post, and seeing they used Ruby, I decided to switch. PeepCode was nice enough to include the dotfiles, so I mostly just adapted that. My prompt now, looks something like:

bin(1hr|master!)☺

Its mostly the same except the time is more descriptive. The older one showed just minutes, which after 2 days since didn’t make sense anymore. This one is a little faster than the older one and in Ruby. It also shows if branch is behind or ahead of remote in terms of commits with ↑ and ↓. I’m not very proud of the code and it is unnecessarily slow at some points, but it works and has a smiley, which I also stole from PeepCode.

I pushed them to my dotfiles repo, if you’re interested. See zshrc and ruby script.

P.S. Both the prompts use color. They’re not visible since I just copied and pasted.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sun, 22 Jan 2012 23:24:00 -0800 Moving away from Singleton pattern for Configuration http://senthilnambi.posterous.com/post/16340392175 http://senthilnambi.posterous.com/post/16340392175

Whenever I wanted to stored some config options for a gem, I go with the singleton pattern. Usually this involves creating a class called Config and letting users configure that with configure block. Think I learned that from Mongoid, don’t remember.

require 'singleton'

module ShinyGem
  class Config
    attr_accessor :options

    include Singleton
  end

  class << self
    def config
      Config.instance
    end

    def configure
      yield config
      config
    end

    def options
      config.options
    end
  end
end

I can do this just once and forget about it. It is easily available anywhere ith Config.instance.options and I can modify it further down the line by opening the block again. The advantage of this approach is only one instance of Config can exist, which is also its disadvantage.

For gems like OpenAuth2, there could be technically be dozens of different api wrappers all using OpenAuth2 under the hood. Can you imagine what would happen then? Panic and chaos in the streets! I didn’t want to get mobbed down the line, so I decided to move away from singleton pattern.

The main requirement here is once config has been setup, it should be available everywhere internally, without me having to pass it each time to “. I decided to make Config a class and pass an instance to Client the first time around. So something like:

config = OpenAuth2::Config.new do |c|
  c.provider = :default
end

# Client
client = OpenAuth2::Client.new(:config => config)

Here’s the code for it.

module OpenAuth2
  class Client
    def initialize(hash={})
      @config = hash[:config]
    end
  end
end

From the client instance I wanted to be able to get access token from Google/Facebook.

client.access_token

Once again, its implementation. Note how config is based here to “ as well.

module OpenAuth2
  class Client
    def access_token
      @access_token ||= AccessToken.new(:config => config)
    end
  end
end

AccessToken stores config in an instance variable as well. The user has to set config up just once and the rest is done internally. And I can switch out the Config instance from Facebook to say Google or just create another Client instance. There could now be dozens of api wrappers in the same environment, all using OpenAuth2. I know, pipe dream indeed.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sun, 22 Jan 2012 23:02:29 -0800 Easy plugin system for your gem in less than 100 lines http://senthilnambi.posterous.com/post/16339765660 http://senthilnambi.posterous.com/post/16339765660

For my OpenAuth2 gem I wanted to let users customize the endpoints and various other options. At first I had a simple configure block, something like:

def configure
  yield self
  self
end

Here users could define options, even procs. Unfortunately every OAuth2 provider seem to have its own take on the implementation and needless to say this leads to lot of headaches. Which is why I decided to hide away the options of big ones like Facebook, Google etc. This way users can set provider = :facebook or provider = :google and not worry about what endpoints or the different options they all use. Also, I wanted to let users define their own providers. The end goal is this:

module OpenAuth2::Provider
  class Facegle < Base
    def options
      {:host => 'http://facegle.com'}
    end
  end
end

OpenAuth2::Config.new.provider = :facegle

The last line tells Config the name of the class to look for options under.

class Base
  attr_accessor :client_id

  def initialize
    @client_id = :default_client_id
    super
  end

  def set_defaults
    options.each do |key,value|
      instance_variable_set("@#{key}", value)
    end
  end
end

When you call provider=, it calls set_defaults which iterates through the hash and sets them to instance variables. That’s one part of it.

Another part is directing the method calls to the right object. const_provider does that job. Here’s rest of the code.

class Config
  Keys = [
    :client_id, 
  ]

  attr_accessor *Keys, :provider

  Keys.each do |key|
    define_method key do
      @provider.send(key)
    end
  end

  # ... some code removed

  def provider=(name)
    @provider = name
    const_provider.set_defaults
  end

  private

  def const_provider
    provider = @provider.to_s.capitalize
    string   = ['OpenAuth2', 'Provider', provider].join('::')
    @provider  = string.constantize.new
  end
end

This piece of code directs client_id to whatever provider is in @provider.

Keys.each do |key|
  define_method key do
    @provider.send(key)
  end
end

One problem here is we can’t override anything that is not set in provider class. What we can do is look for the method locally and if not found, send it to @provider.

Keys.each do |key|
  define_method key do
    instance_variable_get("@#{key}") || @provider.send(key)
  end
end

Here’s the rest of the code: https://gist.github.com/1656550. Amazing how much could be done with less than 100 lines of Ruby code.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Thu, 12 Jan 2012 15:01:39 -0800 Extract out a block into a proc http://senthilnambi.posterous.com/post/15742636900 http://senthilnambi.posterous.com/post/15742636900

Say you’ve something like:

[1,3,5].map do |x|
    x + 1
  end
  # => [2,4,6]

What if you want to reuse the block? You can use a proc to do that.

even_to_odd = proc do |x|
    x + 1
  end

Now you can pass in even_to_odd to the method with &.

[1,3,5].map(&even_to_odd)
  # => [2,4,6]

What if you don’t have an array, but just a single object and you still want that behavior? Instead of passing even_to_odd to the block, you pass in that object to even_to_odd.

even_to_odd.call(1)
  # => 2

Now don’t go extracting out every block into a proc, only when you want to be able to reuse that block.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Tue, 10 Jan 2012 10:52:00 -0800 Getting rspec's "let" method to work in pry http://senthilnambi.posterous.com/post/15627017267 http://senthilnambi.posterous.com/post/15627017267

Backstory: Was writing a google calendar api wrapper gem, since I just worked on a project that required it and also there are no existing gems and very few examples available. Needless to say that led to lot of hair pulling. Guess rubyists don’t care about google api. Anyway, I got a prototype up and running using bdd, and was switching over to pry for manual testing. I use lot of let methods in my specs and this one was no exception. One of them was:

let(:token) do
  "access_token"
end

I copied and posted that in pry and I got NameError: undefined local variable or method let' for main:Object. Well duh, let is a rspec method. Usually I’d copy and paste the string alone, but I had couple more let methos, so I figured I’d just define let in pry. It seemed simple enough, it takes a symbol as argument and sets that to the value in the block. Stupidly I did:

def let(name)
  name = yield
end

Yes, except name is a local variable with scope restricted to just that method body and therefore useless for my purpose. I then changed name to an instance variable and that worked.

def let(name)
  @name = yield
end

pry(main)> @name
=> "access_token"

Expect then I’d have to manually change them all and what’s the point in that. Local variable and instance variable is out of question, so the next option is to define them as a method instead.

def let(name, &block)
  define_method(name, &block)
end

That looked good, I turned the implicit block into an explicit one with &block and passed that along to define_method. Except I got NoMethodError: undefined method define_method' for main:Object. When pry starts, it starts under main and that has no define_method method. Say you’ve a Post class and you cd into that, then you can do define_method, since that is an object.

pry(main)> class Post
  pry(main)* end  

  pry(main)> cd Post

  [8] pry(Post):1> define_method(:hello) {'hi'}
  => #<Proc:0x007f84daa5f2b0@(pry):11 (lambda)>

  [9] pry(Post):1> Post.new.hello
  => "hi"

Just blindly I tried calling define_method on Object class and that almost worked.

def let(name, &block)
  self.class.define_method(name, &block)
end

=>NoMethodError: private method `define_method' called for Object:Class

So I guess it is a private method, no problem, we can use send instead.

def let(name, &block)
  self.class.send(:define_method, name, &block)
end

let(:token) do
  'access_token'
end

[10] pry(main)> token
=> "access_token"

And that’s how you define let to work in pry. This is a fairly simple example, but what was interesting to me was the trial and error process. Figured someone else would benefit from it, rather than just the answer.

EDIT:

Add the method to .pryrc in my root dir and its available every time pry starts now. I think pry has some special syntax for adding methods, but plain `def let` works fine, for now.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Wed, 28 Dec 2011 00:58:00 -0800 Faster specs with DummyTestingPattern http://senthilnambi.posterous.com/post/14911020176 http://senthilnambi.posterous.com/post/14911020176

I’m developing a project for a client that involves a lot of libraries, worse, slow loading libraries that makes doing fast tdd a real pain. One way is to use something like spork, which I do use in Rails, but for a standalone ruby library, it seemed like a overkill, so I decided to use DummyTestingPattern. No, that’s not a real name and yes I just made it up. Btw, I learned this from watching Gary B’s screencasts at destroyallsoftware.com.

Originally the structure was something like this:

# lib/blade.rb
  require 'mongo_mapper'
  require 'stalker'

  class Blade
    def retire(name)
      Stalker.enqueue('retire', :name => name)
    end
  end

  # spec/blade_spec.rb
  require 'blade'

  describe do
    it do
      Stalker.should_receive('enqueue').with('retire', :name => 'leon')
      Blade.new.retire('leon')
    end
  end

If you’re wondering, I watched BladeRunner last night and hence the naming. Great movie, btw.

The problem with the above code is I don’t care about actual Stalker functionality. I just want to make sure Stalker receives the job, not that it actually processes it. Stalker could be an empty module and the above code would still work and we wouldn’t have to incur the cost for loading Stalker each time. So that’s what we’ll do.

# lib/blade.rb
  require 'mongo_mapper'
  require 'stalker'

  module Blade
  end


  # lib/blade/runner.rb
  module Blade
    class Runner
      def retire(name)
        Stalker.enqueue('retire', :name => name)
      end
    end
  end

  # spec/blade_spec.rb
  require 'blade/runner'

  # dummy
  module Stalker
    def self.enqueue(name, hash)
    end
  end

  describe do
    it do
      Stalker.should_receive('enqueue').with('retire', :name => 'leon')
      Blade::Runner.new.retire('leon')
    end
  end

Note we’re not loading the `blade.rb` file, instead we’re directly loading `runner.rb` and stubbing out Stalker. You can do the same for MongoMapper and save all the trips to the db, which btw, is another speed killer.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sun, 30 Oct 2011 10:22:14 -0700 Question driven learning http://senthilnambi.posterous.com/post/12119250519 http://senthilnambi.posterous.com/post/12119250519

I can never sit still enough to finish a class or read a book cover to cover. Yes this could be attributed to our ever decreasing attention span thanks to 100 word articles and top 10 lists or maybe its just my personality, destined to jump from subject to subject, never finish anything. For a while I did feel bad about this and rightly so. After 2 years of learning to program, all I had to show for myself are bunch of unfinished projects, plenty of half read books and a whole lot of unanswered questions.

Let me take a sidetrack and ask you this: when was the last time you were really involved in something? I mean truly experiencing “flow.” The only times I’ve felt that was when I was curious about something, especially the times I was trying to find the answer to some question or trying to solve something. (Mind you I’m talking about programming, but it applies generally as well.) As soon as I find the answer, I lose interest in it, hence the plethora of half baked projects which no longer interest me, mocking me with its halfedness (is that even a word?)

A couple weeks back after trying to understand my failures, I came up with “play based learning” system. The idea here is to not learn the things that you should you need to learn to become a better programmer (I wasn’t a CS major in college and I’ve always felt uneasy about it), but rather just play with it. Find something interesting and take it apart. I even had a flashcard with list of things that I wanted to learn/understand better. That worked great for a while. But soon I got bored.

Once again I tried to figure out what went wrong. I think I just aimed too big this time. I know I’m on the right track, because I felt happy when I was doing it. (There are just way too many crap indicators to tell if you’re being productive or not. The only thing that matters is are you happy when and after doing a particular task.) Also, there weren’t questions that I wanted answers to, but rather general topics.

So I decided to throw out the old flashcard and write a new one. This one had just three entries:

1. How does evented loop actually work internally?
2. What exactly happens when you send a GET, POST request?
3. What was status quo before REST?

As you notice they are all in form of questions. They are the things I was curious about at this moment and I could figure it out before end of today. I’ve decided to throw out the flashcard every night and come up with more questions everyday. This way the material will never get stale, i.e. I won’t lose interest in it.

At the end of the day the goal is to have knowledge of the right tools and the ability to use them properly to get the job done. What does it matter how we go about acquring that knowledge?

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Fri, 22 Apr 2011 00:52:03 -0700 Gmail tips http://senthilnambi.posterous.com/gmail-tips http://senthilnambi.posterous.com/gmail-tips

Few tips on using Gmail:

Learn the shortcuts Press Shift + ? and you’ll see a lightbox open up with all the shortcuts, but I’ve found this to be very unusable. I recommend using this list here, where you can search.

Some of my most commonly used ones:

c – compose g+ i – Go to inbox g + a – Go to all message # – Delete a message / – Search n – Next message p – Previous message j/k – navigation – up/down e – archive enter – open message x – select conversation l – labels r – reply

There are plenty more, but those are the ones I use mostly.

Forward all email to one location I’ve three active Gmail accouts, personal, work and automated. First two are fairly obvious, the third is for signing up to websites I don’t want to give my personal info to. This way I don’t get spammed in my personal email. All three forward to a single account that I check. Haven’t visited the other two in probably weeks. Gmail also allows you to send email from that address, so you can always send email to yours from your work email.

Turn on Google Labs There are dozens of Labs and most are very useful.

Use labels + filters I think labels is my favorite Google labs feature. Currently I’ve ‘Reference’, ‘Waiting’, ‘Work’ and few named project labels on my list. By itself labels is pretty useful, if tedious, but combine that with filters, they become incredibly useful.

For example, all my work emails are tagged “work” automatically since one of my filters catches all email coming to my work email and tags it work. Same for all outgoing email from my work account, it automatically gets tagged. I also have couple work based filters, but I don’t really find them that useful.

Also all my outgoing email gets tagged “Waiting” indicating that I’m waiting for a response from someone.

Hope you found them useful.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sun, 17 Apr 2011 20:00:27 -0700 Productivity tips: Part 2 http://senthilnambi.posterous.com/productivity-tips-part-2 http://senthilnambi.posterous.com/productivity-tips-part-2

Some more productivity tips I’ve noticed the last couple weeks:

Use full screen when reading – I do most of my reading in either Readability or pdfs. Sometimes I inadvertently press alt + tab. I can do with full screen too, but I don’t.

Have a collection bin – I use a combination of pen + pad & Thinkery to track things. This is directly from GTD where its paramount to jot things down so you don’t let it linger in your mind and cloud your thought process. Don’t worry about formatting it or prettying it up, use it at will, write everywhere, its just a temporary place to hold your notes, not a permanent location, so fire away.

Go out of read – Get a kindle! It seriously rocks. I’ve been going to a park nearby and reading books off my Kindle. The distraction free environment combined with natural air makes for great reading atmosphere. Don’t take your laptop with you, trust me you’ll get distracted and spend more time on there than reading, at least I do.

Have an actionable todo list – Having a general outline in mind is good, but doesn’t help me get started. I need to see the next physical action I can do to move the project ahead or I just procrastinate, even just one todo helps. Get that done and do the next one.

Measure – I’ve been using Freckle the last couple days to keep track of how much time I spent actually working, opposed to the time in between. Turns out I wasn’t nearly as much as I thought I was. Don’t rely on your memory, it will fool you. At first I tried measuring too many things, but it was way too much work and quit midway. Start small and do it for at least 7 days.

Review constantly – Most of us usually know all the things that’s required to achieve success, but we don’t practice. Sometimes its due to laziness, other times you need to reminded of things, for me this involves reviewing this list every couple days so I don’t forget.

Start early – I’m usually very lazy in the mornings and if I’m not excited about something, I barely get any work done. One of the things I’ve noticed is the things I do the first 30-60 minutes sets the tone for rest of the day. A while back I decided to spend at least 30 minutes learning about Rails and blogging about it, but that feel through after a week. Yesterday I felt guilty and did learn/write a blog post and that set the tone for rest of the day.

I’m going to stop right here since I don’t want this blog to become a productivity blog, like there aren’t enough of those. Will get back to regular programming about Rails from now on.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sat, 16 Apr 2011 16:47:40 -0700 Module#attr_accessor_with_default http://senthilnambi.posterous.com/moduleattraccessorwithdefault http://senthilnambi.posterous.com/moduleattraccessorwithdefault

Today we’re going to look into Module#attr_accessor_with_default which as the name suggests sets up a default value for an accessor. Say you’re writing a Blog cms, since there are clearly not enough of those, and you want to setup some default entires for future Posts, i.e. author name etc. You can hard code them or you can setup a default value. One way to do it is in model:

class Post
  key :author_name, :default => "Darth Vader"
end

But what if you didn’t have access to Mongomapper or any ORMs. This is where Module#attr_accessor_with_default comes into play. You can do this:

class Post
  attr_accessor_with_default :author_name, "Darth Vader"
end

Apparently you can do even something like this:

class Post
  attr_accessor_with_default :author_name {name.humanize}
end

Where the block is evaluatied in scope of self, but I keep getting undefined local variable or method name'

Here’s the actual implementation code from ActiveSupport

def attr_accessor_with_default(sym, default = Proc.new)
  define_method(sym, block_given? ? default : Proc.new { default })
  module_eval(

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Wed, 13 Apr 2011 19:14:18 -0700 Keyboard shorcuts http://senthilnambi.posterous.com/keyboard-shorcuts http://senthilnambi.posterous.com/keyboard-shorcuts

Remember yesterday how I said I use keyboard to do most of navigation/tasks on my laptop? Well here’s a quick list of the stuff I commonly use.

Firefox

cntrl + D – Bookmark this page cntrl + shift + O – Open bookmark organizer cntrl + / – Show/hide bottom bar cntrl + G – Find next cntrl + Shift + G – Find previous cntrl + Shift + E – Open tab groups view cntrl + k – Put pointer in search cntrl + l – Put pointer in url alt + up/down – Change search source

F9 – Open Firebug F11 – Full screen Alt + F9 – Resize window Alt + F10 – Minimize window

Bookmarklets You’ll have to setup keywords (shortcuts) in Bookmark organizer page first. To use these, go to url bar and type in the following and the first result will be the right bookmark.

th – Bookmark page in thinkery tm – thinkery.me homepage f – letsfreckle homepage

Compiz

alt + w – Open window picker alt + w – Open window picker for similar windows

cntrl + super + right/left – Move right/left virtual window super + tab – Shift window picker supe + tab + shift – Go the other way

cntrl + shift + 1-7 – Move window to left/right + top/bottom/middle of screen

gedit

cntrl + k – Quick find cntrl + shift + o – Open recent windows cntrl + super + o – Fuzz open (Make sure to set right root folder in sidebar F9)

Pandora

spacebar: Toggle Play / Pause right-arrow: Skip to the Next Song plus: I Like this Song minus: I Don’t Like this Song up-arrow: Raise Volume down-arrow: Lower Volume shift + up-arrow: Full Volume shift + down-arrow: Mute

General

alt + first letter – Usually opens up menu bar dropdown alt + F – opens up File menu dropdown

cntrl + shift + n – Opens up new window of current program. I primarily use it for opening up new terminals.

This isn’t an exhaustive list, but something to help get started. Don’t try to memorize them all at once, thought you certainly can, except you’ll stop using it after couple days feed up with having to look up each shortcut or confusing one for another. Start with the program you use the most and slowly add newer ones. I suggest Firefox or if you’re like me, gedit.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Wed, 13 Apr 2011 03:59:58 -0700 Freckle, Thinkery and more user interface lessons http://senthilnambi.posterous.com/freckle-thinkery-and-more-user-interface-less http://senthilnambi.posterous.com/freckle-thinkery-and-more-user-interface-less

Recently I signed up for bunch of new sites like Frekcle, [Mint] and [Thinkery]. Here’s a list of cool features I found in them and couple other I’ve seen in other sites, mostly to do with improving user experience.

Keyboard shortcuts – Ever since I took the time to learn [Gmail shortcuts], I’ve fallen in love with them. For the most part I use keyboard to navigate and do other stuff on Gmail and in general. One thing I hate about Gmail keyboard navigation is that some of it isn’t very intutitive and there are just way too many options.

Secondly, the cheatsheet for shortcuts must be available easily. In Gmail typing shift + ? opens up a handly little lightbox, only problem is there’s way too many options there and finding the one you want is a bit difficult.

This is almost a must in websites like Project managment, bookmark organizer and any site involving quick addition of entires. Thinkery takes it a bit further with option to edit/archive/delete using keyboard shortcuts. I don’t care if I’ve to use the mouse to change my profile picture, but for the tasks we do often keyboard shortcuts is a must.

Search/Adding new resouce in same text box – I first saw this on [Quora], the box you use to search for questions is the same you use to add new ones. At first it was a bit confusing, but I really started to like it after that. It greatly reduces duplicate entires, due to instant search. So no more yelling at the newb who doesn’t know how to use search (forums I’m looking at you). Thinkery uses it too, except the search isn’t as instaneous as Quora so you’ll have to wait that extra couple seconds.

Import data – Say you want to switch to [Apollo] project management from [Basecamp], except you can’t since you’ve about 1000 todos on Basecamp. That is unless Apollo offers a way to import the data, which they do. When I was contemplating my switch, I nearly didn’t since I didn’t want to manually enter in the data. The import feature made me make the switch, but then I switched back. Say what you’ll about 37 Signals and their people, nothing beats the simplicity and easeness of Basecamp, except maybe a pen and pad.

Tags for organizing – This one is pretty commonplace these days. I really like Thinkery’s use of tags to combine a todolist + readitlater + bookmarking service. For example, I have the following tags “Read” “Todo” “Url” “Video”, all of them are pretty much the same resource in the backend, but entirely different entities.

Freckle takes it further by letting us specify a tag as billable or not using * at end of the tag. Also, an ! at beginning of tag makes it an description rather than creating a new tag.

Bulk add/edit/delete options – I don’t have time or patience to do things individually, and I naturally assume the user’s time to be way more valuable than mine. Gmail allows you to choose all the email that match a certain category or keyword search and do actions to them, not just the email on the page. I’ve found that to be very useful when dealing with thousands of emails.

Bookmarklets – Its almost required if you’re in bookmarking. [Zootool] is an amazingly useful app, which scrapes the pictures in the page and saves them. The only problem is it is very slow. Most of the time I don’t want to wait 5+ seconds, which is where something like Thinkery really shine, since it does the scraping/processing in the background. Or it does it very fast, since I’ve noticed very little wait.

These are just couple things I’ve noticed when trying out the new sites. This is more of a list in progress than anything. I don’t know about you guys, but I’m very excited for the future of the web, especially when it comes to these little things that vastly improve user experience.

I should probably do a post on mint exclusively, since that site is just a goldmine for user experience lessons.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Tue, 05 Apr 2011 18:04:17 -0700 Productivity tips http://senthilnambi.posterous.com/productivity-tips http://senthilnambi.posterous.com/productivity-tips

Here are couple things I’ve noticed over the years:

Close your browser – Better yet turn off your Internet, but I need Google for work, so the latter isn’t an option. However when I’ve firefox open I feel the urge to entertain every question that pops into my mind. I’ll be reading about something and suddenly something else will pop up and before you know it I’m on wikipedia reading about Otto Von Bismarck. One thing that kept the browser open was Pandora, the online radio channel, so I upgraded to Pandora premium offering and they had this nice Adobe Air app that runs on my desktop. So no more Firefox.

Clear out your history – Sometimes inadvertently I’ll open up a tab and type in d in my browser url bar and click digg. Most of the time I don’t consciously think I’m going to waste the next 10 minutes reading about crap, it just happens. But with the history cleared, I’ll need to type in the entire digg.com. Sure I can easily type it in, but most of the time I don’t. I just close the tab and go back to doing something else.

Clear your working space – Stephen Covey has a very good explanation of why this is useful in Art of War “He (The professional) will not tolerate disorder. He eliminates chaos from his world in order to banish it from his mind. He wants the carpet vacuumed and the threshold swept, so the Muse may enter and not soil her gown.” I like having an empty table with just my laptop and some notes pertaining to the project at hand. Nothing else. I don’t care if everything else in the room is disordered, but my working space has to be clear of chaos.

Have everything you need at hand – Whether it is pencil and pad to jot down notes or your reference material, have them at hand. Nothing irritates me more than having to get up and find something while I’m on a roll and nothing ruins my concentration more either.

Make list of todos, rather than doing them right away – If you’re doing something and you suddenly think of a new task, relevant or irrelevant to what you’re doing, jot them down or capture them somehow, instead of doing them right away. Even if it is related to what you’re doing, jot it down anyway. This way you don’t get distracted from what you’re doing and you don’t have to worry about forgetting it.

Stay away from gaming sites – Not sites about gaming, but sites like digg, reddit, twitter, tumblr, foursquare etc, pretty much anything that relies on variable reinforcement. Twitter, especially is the worst of them all. You don’t get a reply or find something you like every time you check it, you get it sometimes, most often you don’t and that just drives you to check it more often worsening the problem.

Sign out of any services – Especially Gmail, since I don’t use any other service that’s highly addicting. It helps my password is bit difficult to type in, so I don’t mindless type it in, usually I’ve to wait a second and think about it. When all it takes is typing in the url, you tend to do it often, but if you’ve to sign in each time, it takes a bit longer. Usually that’s enough for me to close it.

Go on low information diet – I’ve been trying to stay away from news sites and really narrow down my information uptake only in areas that I really care about, or rather my focus right now, i.e. Ruby. No more reading about Rome or music or things that I care about, but not enough to make it my life’s work. Obviously this is a great way to develop tunnel vision, so I recommend spending at least one day/week reading about things that are completed unrelated.

Use Instapaper/readabilityDavid Allen recommends capturing any task that takes more than 2 minutes, while completing others right away. That technique also works for reading. Read anything you can in 2 minutes and capture the rest so you can go back to it. Most of the time I end up skipping them anyway.

These are just some tips I’ve noticed that works for me. Hopefully it helps someone else out there too.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sun, 03 Apr 2011 18:00:00 -0700 ActiveSupport#cattr_accessor http://senthilnambi.posterous.com/activesupportcattraccessor http://senthilnambi.posterous.com/activesupportcattraccessor

Today we’ll see how ActiveSupport.cattr_accessor works. What does cattr_accessor do? Think of it as Class#attr_accessor which has you know creates getter and setters methods on class' instances, but for class itself. One gotcha is if a subclass changes the value, then the parent class' will reflect that change, due to its use of @@ or class variables to store the information.

We’ll look at cattr_reader first, which is similar to attr_reader

def cattr_reader(*syms)
  options = syms.extract_options!
  syms.each do |sym|
    class_eval(<<-EOS, __FILE__, __LINE__ + 1)
      unless defined? @@#{sym}
        @@#{sym} = nil
      end

      def self.#{sym}
        @@#{sym}
      end
    EOS

    unless options[:instance_reader] == false
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def #{sym}
          @@#{sym}
        end
      EOS
    end
  end
end

cattr_reader :title, :author

The first line calls extract_options! which is another AS method. It simply looks to see if the last argument is Hash and pops out that. The extractable_options? checks to see if the Hash instance. If you were to create a subclass of Hash, you can implement the method to return true.

def extract_options!
  if last.is_a?(Hash) && last.extractable_options?
    pop
  else
    {}
  end
end

The core of the method is to open the class and define a class method that reads @@ or class variable and it does it for each argument to cattr_reader.

class_eval(<<-EOS, __FILE__, __LINE__ + 1)
  unless defined? @@#{sym}
    @@#{sym} = nil
  end

  def self.#{sym}
    @@#{sym}
  end
EOS

First, if @@ already exists, it does nothing, else it sets to nil. Next, it defines the class method which simply returns the class variable. Finally it sets an instance method, but only if user doesn’t disallows it.

unless options[:instance_reader] == false
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
    def #{sym}
      @@#{sym}
    end
  EOS
end

cattr_writer is almost the same thing, but for a setter method.

def cattr_writer(*syms)
  options = syms.extract_options!
  syms.each do |sym|
    class_eval(<<-EOS, __FILE__, __LINE__ + 1)
      unless defined? @@#{sym}
        @@#{sym} = nil
      end

      def self.#{sym}=(obj)
        @@#{sym} = obj
      end
    EOS

    unless options[:instance_writer] == false
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def #{sym}=(obj)
          @@#{sym} = obj
        end
      EOS
    end
    self.send("#{sym}=", yield) if block_given?
  end
end

The one difference is that it accepts a block, say cattr_writer :title do "Jonesy" end. cattr_accessor does nothing but combine the two.

def cattr_accessor(*syms, &blk)
  cattr_reader(*syms)
  cattr_writer(*syms, &blk)
end

The one thing I don’t like is it is using class_eval (mostly because it involves strings), when the same thing can be done with define_method. Tomorrow we’ll see how to do it using define_method instead

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Sat, 02 Apr 2011 20:40:41 -0700 Mongoid#field http://senthilnambi.posterous.com/mongoidfield http://senthilnambi.posterous.com/mongoidfield

Its been a while since I made a post about Mongoid, so here we go. Today we’re going to look at Mongoid::Fields, which as you know is used to define fields in a documents. Here’s the offical description:

Defines all the fields that are accessible on the Document. For each field that is defined, a getter and setter will be added as an instance method to the Document.

Let’s look the ClassMethods first.

def field(name, options = {})
  access = name.to_s
  set_field(access, options)
  attr_protected name if options[:accessible] == false
end

The core of the method is set_field():

def set_field(name, options = {})
  meth = options.delete(:as) || name
  fields[name] = Field.new(name, options)
  create_accessors(name, meth, options)
  add_dirty_methods(name)
end

options(:as) is used to delegate model name, i.e. field :name, :as => :title. The second line fields[name] creates new instance of Field and sets that to a hash. Here are the getter and setter methods for fields, nothing special just creates a Hash and sets that to an instance variable.

def fields
  @fields ||= {}
end

def fields=(fields)
  @fields = fields
end

Field#initialize mostly sets instance variables and calls check_default!, we’ll worry about that later.

def initialize(name, options = {})
  @type = options[:type] || Object
  @name, @default, @label = name, options[:default], options[:label]
  @copyable = (@default.is_a?(Array) || @default.is_a?(Hash))
  @options = options
  check_default!
end

Getting back to set_field, in third line create_accessors does exactly what it says, it creates accessors methods, i.e. getter, setter and predicate methods with some metapogramming magic.

def create_accessors(name, meth, options = {})
  generated_field_methods.module_eval do
    define_method(meth) { read_attribute(name) }
    define_method("#{meth}=") { |value| write_attribute(name, value) }
    define_method("#{meth}?") do
      attr = read_attribute(name)
      (options[:type] == Boolean) ? attr == true : attr.present?
    end
  end
end

The first line is a bit odd, it calls module_eval on generated_field_methods, which as you can see just creates a Module and returns it using tap so we can call module_eval on it.

def generated_field_methods
  @generated_field_methods ||= begin
    Module.new.tap do |mod|
      include mod
    end
  end
end

To summarize defining field on a model creates a Field instance, then sets accessor methods in a module.

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil
Fri, 01 Apr 2011 23:22:00 -0700 Noun Project download all script http://senthilnambi.posterous.com/noun-project-download-all-script http://senthilnambi.posterous.com/noun-project-download-all-script

I came across the Noun Project today and was blown away by its detail and sheer size. For some reason they don’t have an option to download all the files at once, so I wrote a script to do that. It’s nothing fancy, took me less than 30 minutes. Noun Project is down right now, so I can’t test it in real life, but as far as I can tell it does work and will when site comes back up.

EDIT: The site is back up and the script works. It also extracts the contents into a single directory. As of writing this (April 02, 2011), there are 625 files, but unfortunately out some are missing in the server or at a different location, so only 396 of them are actually downloaded. Maybe I should’ve scrapped the actual download location from the site.

require 'rubygems'
require 'fileutils'
require 'zip/zip'

class Downloader
  attr_reader :base_url, :video_number, :total_videos
  attr_accessor :full_url

  def initialize(total_videos)
    @base_url = "http://www.thenounproject.com/site_media/zipped/"
    @video_number = 1
    @total_videos = total_videos
    @download_dir = make_download_dir
  end

  def download_all_videos
    until total_videos+1 == video_number
      @full_url = base_url + "svg_#{video_number}.zip"
      system("cd #{@download_dir} && wget #{full_url}")

      # Some files aren't being downloaded, not sure if files are missing in server 
      # or server timing out
      sleep 0.25
      @video_number += 1
    end
  end

  def extract_dirs
    array = Dir.entries("noun-project")
    array.delete("."); array.delete("..");
    array.each { |zipped_file| unzip_file("noun-project/#{zipped_file}", "extracted_contents") }
  end

  # Taken from http://stackoverflow.com/questions/966054/how-to-overwrite-existing-files-using-rubyzip-lib
  def unzip_file(file, destination)
    Zip::ZipFile.open(file) { |zip_file|
     zip_file.each { |f|
       f_path=File.join(destination, f.name)
       if File.exist?(f_path) then
         FileUtils.rm_rf f_path
       end
       FileUtils.mkdir_p(File.dirname(f_path))
       zip_file.extract(f, f_path)
     }
    }
  end

  private

  def make_download_dir
    Dir.exists?("noun-project") || Dir.mkdir("noun-project")
    "noun-project"
  end
end

puts "How many videos are there in total? (Default = 629)"
number = gets.to_i
number = number == 0 ? 629 : number

dl = Downloader.new(number)
dl.download_all_videos
dl.extract_dirs

require 'rspec'

describe Downloader do
  before(:each) do
    @dl = Downloader.new(1)
  end

  it 'should create download dir if it does not exist' do
    Dir.exists?("noun-project").should == true
  end

  it 'should return default total videos url' do
    @dl.total_videos.should == 1
  end

  it 'should download 1 file' do
    Dir.entries("noun-project").size.should == 3
  end
end

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/hdKZ22etBp3iW senthil senthil senthil