One of the things I enjoy working at RSB is the 10% personal project time given to each team member to pursue their own interest (sure, we’ve all heard about Google’s 20% time and we hope reach that as we grow). Anyway, that works out to 4 hours or one afternoon’s worth of time. I choose to focus this time on building the Malaysia.rb community.

Ever since Malaysia.rb started in May 2007, we’ve had regular monthly meetups every third Thursday of the month at various locations in the Klang Valley. And, with the first meetup of 2008 coming upon us this week, it is my duty to send out the event announcement:

Malaysia.rb is kicking off 2008 with a bang! The January 2008 Meetup is happening this Thursday and it’s gonna seriously rock.

Four reasons why you shouldn’t miss this meetup:

  1. Meeting room with AV facilities and FOOD - MDEC has graciously stepped up to sponsor this month’s location.
  2. Special guest, Colin Wong, a Malaysian ex-Googler turned investor. Look out for his talk details below.
  3. Free pre-meetup PeepCode screening of “Rails From Scratch Part I” for early birds
  4. Two free PeepCode episodes to be won

When:

Thursday, January 17th 2008, 8:00PM

Agenda:

  7:00 - 8:00pm   Pre-meetup PeepCode screening
  8:00 - 8:15pm   Opening by the Organizer
  8:15 - 8:45pm   "From Batu Gajah to Mountain View and Beyond" - Colin Wong
  8:45 - 9:15pm   "Rails Fragment Caching with Interlock" - Kamal Fariz
  9:15 - 9:35pm   Open Lightning Talks
  9:35 - 9:45pm   PeepCode episode lucky draw and close

Cost:

Free. No registration required, just come right in, have a seat, and join the crowd. Invite your friends.

Contact:

kamal.fariz@gmail.com
+60123099143

Where:

PJ Hilton
No 2 Jalan Barat
46200 Petaling Jaya
Malaysia
Location

Directions:

Take the Kelana Jaya LRT line to Asia Jaya. It’s across the Federal Highway from there.

Hope to see you there!

UPDATE The meetup location is now confirmed to be at PJ Hilton. Please RSVP directly to me if you plan on attending so that I can estimate the number of people coming (for food, mostly).

Prerequisite

  1. Install git

    sudo apt-get install git-core
    

Initializing gitosis

  1. Grab gitosis

    kamal@dev:~$ git clone git://eagain.net/gitosis.git
    Initialized empty Git repository in /home/kamal/gitosis/.git/
    remote: Generating pack...
    remote: Done counting 549 objects.
    remote: Deltifying 549 objects...
    remote:  100% (549/549) done
    Indexing 549 objects...
    remote: Total 549 (delta 379), reused 136 (delta 95)
     100% (549/549) done
    Resolving 379 deltas...
     100% (379/379) done
    
  2. Install gitosis

    kamal@dev:~/gitosis$ cd gitosis && sudo python setup.py install
    running install
    running bdist_egg
    running egg_info
    creating gitosis.egg-info
    ...
    Installing gitosis-init script to /usr/bin
    Installing gitosis-run-hook script to /usr/bin
    Installing gitosis-serve script to /usr/bin
    
    Installed /usr/lib/python2.4/site-packages/gitosis-0.2-py2.4.egg
    Processing dependencies for gitosis==0.2
    Finished processing dependencies for gitosis==0.2
    
  3. Create the git user on the server

    kamal@dev:~$ sudo adduser \
    >        --system \
    >        --shell /bin/sh \
    >        --gecos 'git version control' \
    >        --group \
    >        --disabled-password \
    >        --home /var/local/git \
    >        git
    Adding system user `git' (UID 106) ...
    Adding new group `git' (GID 109) ...
    Adding new user `git' (UID 106) with group `git' ...
    Creating home directory `/var/local/git' ...
    
  4. Back on your local machine, scp your SSH public key to the server

    MacBook-Pro:~ kamal$ scp ~/.ssh/id_dsa.pub dev.ror.com.my:/tmp
    id_dsa.pub                                    100%  613     0.6KB/s   00:00
    
  5. Back on the server, initialize gitosis

    kamal@dev:~/gitosis$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
    Initialized empty Git repository in ./
    Initialized empty Git repository in ./
    
  6. Back on your local machine, clone the automatically created gitosis-admin project

    MacBook-Pro:~ kamal$ git clone git@dev.ror.com.my:gitosis-admin.git
    Initialized empty Git repository in /Users/kamal/gitosis-admin/.git/
    remote: Generating pack...
    remote: Done counting 5 objects.
    remote: Deltifying 5 objects...
    remote:  100% (5/5) done
    remote: Total 5 (delta 1), reused 5 (delta 1)
    Indexing 5 objects...
     100% (5/5) done
    Resolving 1 deltas...
     100% (1/1) done
    
  7. Check out the contents of gitosis-admin

    MacBook-Pro:~ kamal$ cd gitosis-admin/
    MacBook-Pro:gitosis-admin kamal$ ls
    gitosis.conf    keydir
    MacBook-Pro:gitosis-admin kamal$ more gitosis.conf
    [gitosis]
    
    [group gitosis-admin]
    writable = gitosis-admin
    members = kamal@MacBook-Pro.local
    
    MacBook-Pro:gitosis-admin kamal$ ls keydir/
    kamal@MacBook-Pro.local.pub
    

    Note: The main configuration file lives in gitosis.conf and the users are identified by their SSH public keys which are in keydir

Adding Users

  1. Adding Aizat as a gitosis-admin member is easy

    MacBook-Pro:gitosis-admin kamal$ cp /tmp/aizat-id_dsa.pub keydir/aizat@Zatto.local.pub
    

    Note: The filename in the keydir has to match the last bit in the public key file plus .pub

  2. Edit gitosis.conf

    [gitosis]
    
    [group gitosis-admin]
    writable = gitosis-admin
    members = kamal@MacBook-Pro.local aizat@Zatto.local
    
  3. Add the new file to git

    MacBook-Pro:gitosis-admin kamal$ git add keydir/aizat\@Zatto.local.pub
    
  4. Commit the changes

    MacBook-Pro:gitosis-admin kamal$ git-commit -a -m "Added Aizat as a gitosis admin"
    Created commit 37c0966: Added Aizat as a gitosis admin
     2 files changed, 2 insertions(+), 1 deletions(-)
     create mode 100644 keydir/aizat@Zatto.local.pub
    
  5. And push to the server

    MacBook-Pro:gitosis-admin kamal$ git push
    updating 'refs/heads/master'
      from 3b5462b027a02a5b29bf43f4ca878350ccc8b913
      to   37c0966f285715cc38bd801a3955bb6f319ccdf4
     Also local refs/remotes/origin/master
    Generating pack...
    Done counting 8 objects.
    Result has 5 objects.
    Deltifying 5 objects...
     100% (5/5) done
    Writing 5 objects...
     100% (5/5) done
    Total 5 (delta 1), reused 0 (delta 0)
    refs/heads/master: 3b5462b027a02a5b29bf43f4ca878350ccc8b913 -> 37c0966f285715cc38bd801a3955bb6f319ccdf4
    
  6. To add non-admin users, the process is the roughly the same. You only need to create a new group in gitosis.conf.

Adding Projects

  1. Add a new group for other users and set a new test project as the writable project

    [gitosis]
    
    [group gitosis-admin]
    writable = gitosis-admin
    members = kamal@MacBook-Pro.local aizat@Zatto.local
    
    [group rsb]
    writable = test_project
    members = @gitosis-admin kegan@MacBook.local saimer@MacBook.local seanx2@Dell.local
    
  2. Commit and push

    MacBook-Pro:gitosis-admin kamal$ git-commit -a -m "Added a new group for RSB and set write perms on a new test project"
    MacBook-Pro:gitosis-admin kamal$ git push
    updating 'refs/heads/master'
      from 37c0966f285715cc38bd801a3955bb6f319ccdf4
      to   2fc5d9c394218fb757ce6fe468b9ea8096e99dcf
     Also local refs/remotes/origin/master
    Generating pack...
    Done counting 8 objects.
    Result has 6 objects.
    Deltifying 6 objects...
     100% (6/6) done
    Writing 6 objects...
     100% (6/6) done
    Total 6 (delta 1), reused 0 (delta 0)
    refs/heads/master: 37c0966f285715cc38bd801a3955bb6f319ccdf4 -> 2fc5d9c394218fb757ce6fe468b9ea8096e99dcf
    
  3. Create the test project

    MacBook-Pro:~ kamal$ mkdir test_project
    MacBook-Pro:~ kamal$ cd test_project/
    MacBook-Pro:test_project kamal$ git init
    Initialized empty Git repository in .git/
    MacBook-Pro:test_project kamal$ git remote add origin git@dev.ror.com.my:test_project.git
    MacBook-Pro:test_project kamal$ echo "This is an test project hosted in git" > README
    MacBook-Pro:test_project kamal$ git add README
    MacBook-Pro:test_project kamal$ git commit -a -m "Added a README file"
    Created initial commit f70c2f7: Added a README file
     1 files changed, 1 insertions(+), 0 deletions(-)
     create mode 100644 README
    

    Note: It is important that you have files to add, otherwise the next command will fail. I think this has to do with git not tracking empty directories?

  4. Push the test_project to the server

    MacBook-Pro:test_project kamal$ git push origin master:refs/heads/master
    updating 'refs/heads/master'
      from 0000000000000000000000000000000000000000
      to   f70c2f74d71fbbb1edd0f5da2554fd208f75051b
     Also local refs/remotes/origin/master
    Generating pack...
    Done counting 3 objects.
    Deltifying 3 objects...
     100% (3/3) done
    Writing 3 objects...
     100% (3/3) done
    Total 3 (delta 0), reused 0 (delta 0)
    refs/heads/master: 0000000000000000000000000000000000000000 -> f70c2f74d71fbbb1edd0f5da2554fd208f75051b
    
  5. Test out by cloning the project

    MacBook-Pro:~ kamal$ git clone git@dev.ror.com.my:test_project.git test_project2
    Initialized empty Git repository in /Users/kamal/test_project2/.git/
    remote: Generating pack...
    remote: Done counting 3 objects.
    remote: Deltifying 3 objects...
    remote:  100% (3/3) done
    remote: Total 3 (delta 0), reused 0 (delta 0)
    Indexing 3 objects...
     100% (3/3) done
    

And you’re done!

In the next article, I will explore migrating existing Subversion repositories to git. Stay tuned!

That’s not a typo! It’s supposedly a programmer’s joke… something about recursion (no, of course the CSS dev wasn’t the one who came up with that, geez :P) :x

Big kudos to Moo who planned our first outing–dinner and a movie! ^^;

Kegan and Lee Ching Kegan and Lee Ching

Kamal and Mai Kamal and Mai

Moo and Wendy Moo and Wendy

Sean Sean

The food had excellent reviews (as seen by everyone’s big, happy, cheeky grins right after dessert):

Group picture! :) Group picture! :)

Unfortunately, I am Legend had mixed reviews: the guys enjoyed it while I found the start to be quite a huge bore and the ending somewhat lackluster. Think literal crosseyed confusion as to what the heck just happened at the end…

For more pictures from the RSB Super Barty event (more yummy pictures of the food and shots of people taking pictures of other people), check out our Time Together entry on Facebook :)

Aizat missed it, but was there with us in spirit! We’re so hocking Ninja Jones when he comes back from Chile, eh? ;)

MDec InnoTech.my 2007

What a great event! … the MDeC InnoTech.my 2007, held on Friday, 7 Dec. Congratulations to MDeC TeDD team for pulling this off.

This year’s forum was themed “Connecting Innovation, Capital and Technopreneurs” where various VCs from different parts of the world (namely US, India and China) spoke.

A particular VCs that we Malaysian can probably better relate to, is Colin Wong. Colin was born in Batu Gajah, Perak, an ex-Googler, the founder & president of Prosperati, and now the CEO of ZoeCity.

Colin started off by presenting the VC landscape in the US–the top three investment areas were software (USD$1.11B, Q3 2007), biotechnology (USD$1.1B, Q3 2007), and clean technology (USD$844m, Q3 2007). It was also noted that there was an investment trend shift towards internet/consumer media, consumer hardware, and material science. Regardless, Silicon Valley remains as the top US innovation ecosystem, where research (universities) meets venture capitalism and entrepreneurs.

The gist of Colin’s talk was about risks and failures. Both the VCs and entrepreneurs in Malaysia shouldn’t be afraid of taking risks in new ventures that may not have proven business models, management teams or technologies.

Fail fast, fail often to find success. It’s all about risk.

(And yes, Colin, it would be awesome if MDeC were to set up office in Silicon Valley ;))

All in all a great event, except there was no vegetarian food for lunch (ouch!).

* Picture courtesy of my friend Azrul

… namely the UI Developer: me.

I’m not even going into the Rails file structure. However, just know that if you want to make your Rails programmer’s life much, much easier (and to make sure they won’t pee in your shampoo, ever) put your files in the public folder. Needless to say, images go in the public/images folder and stylesheets in public/stylesheets. Simple, yes?

Okay, fluff aside and since sharing is caring, today I’ll be sharing the first three sexy lines of Rails code I picked up!

THE BASIC

What’s a UI dev without his/her stylesheet? So first thing’s first: call that stylesheet!

<%= stylesheet_link_tag 'style' %>

Rails is intelligent enough to know that your stylesheets are indeed stylesheets and they’re housed in the public/stylehseets folder without you actually having to specify! How nifty is that? :)

THE SIMPLE BITS

How linking works in Rails:

<%= link_to('RSB, holla!', 'http://blog.ror.com.my') %>

which is actually your

<a href="http://blog.ror.com.my">RSB, holla!</a>

FUN STUFF

Making those images prettier with image_tag

Because Rails is emazing at compacting code, your generic <img src="images/spiffy.png" alt="spiffy!" class="wrapper" /> now becomes:

<%= image_tag 'spiffy.png', :class => 'wrapper', :alt => 'spiffy!' %>

Alrighties, so we’ve gotten the easy part out of the way :) Next week we’ll dive a little into how partials and conditionals work! :) And no, it’s not rocket science, it’s Ruby magic!

p/s: It is secretly fun harassing Kamal for code logic! :P

I was at MIMOS Technology Forum 2007 yesterday. Met a couple of friends from Cradle, there was Dato’ Abdul Wahab Abdullah (MIMOS Preseident and CEO), Dato’ Kong Cho Ha (Deputy Minister, MOSTI), and some really smart researchers.

MIMOS Technology Forum 2007

What I find most interesting is that the amount of R&D MIMOS is cooking up in their kitchen.

In particular, MIMOS has a project called Wi-Wi. This was presented by Dr. Mazlan Abbas (MIMOS’s Head of Wireless Comm Cluster). Wi-Wi is a MIMOS patented wireless technology, featuring peer-to-peer WiMax-Wifi combo that promise to bring wireless Internet access to the most remote part of our country. The device is small enough to be mounted on lamp post, and …. well, you get the idea.

Now here is something for MIMOS to think about. Instead of having one (or a few) monopolistic company deploying Wi-Wi, make Wi-Wi device easy enough for anyone that want to deploy it. And that person get to share the revenue generated from his Wi-Wi device. This is not dissimilar to FON.

So Wi-Wi, … something to watch out for!

Unfortunately I did not manage to stay for the whole event, as I have to run for a workshop (which is awesome by the way, but that’s for another post).

Rails Routing and Facebook’s POSTs

If you have done any amount of Facebook development with Rails, you will quickly encounter the number one thing that has pissed off every Rails developer - Everything Is A POST!

With Facebooker’s pseudo-resource route generator, things are not so bad. It allows us declarations such as

  facebook_resources :entries
  facebook_resources :photos

in config/routes.rb which is nice and concise. However, the paths generated are so old school!

  GET    /entries            # index
  GET    /entries/new        # new
  POST   /entries/create     # create
  GET    /entries/1/show     # show
  GET    /entries/1/edit     # edit
  POST   /entries/1/update   # update
  POST   /entries/1/destroy  # destroy

Yuck!

Rails taught us to love HTTP verbs, did it not? The above could be simplified if we took into account the HTTP request method, like so,

  GET    /entries            # index
  GET    /entries/new        # new
  POST   /entries            # create
  GET    /entries/1          # show
  GET    /entries/1/edit     # edit
  PUT    /entries/1          # update
  DELETE /entries/1          # destroy

Unfortunately, you are stuck with just POST, buddy. Don’t even dream about your PUT and DELETE. Is there anything we can do? Fortunately, yes!

We Can Have Our RESTful Routes Back!

So, how do you solve this with Facebook? Facebook very recently added an additional request parameter to disambiguate between GET and POST via fb_sig_request_method. The actual requests from Facebook are still POSTs but we can make use of fb_sig_request_method as an added condition in our routes.

This is how you do it. Stick the following piece of code in lib and require it in a config/initializers file, or if you are using Facebooker as a plugin, modify vendor/plugins/facebooker/lib/facebooker/rails/routing.rb

  def facebook_resources(name_sym)
    name = name_sym.to_s

    with_options :controller => name, :conditions => { :method => :post } do |map|

      map.with_options :conditions => { :fb_sig_request_method => 'GET' } do |get|
        get.named_route("new_#{name.singularize}",  "#{name}/new",       :action => 'new')
        get.named_route(name,                       name,                :action => 'index')
        get.named_route(name.singularize,           "#{name}/:id",       :action => 'show', :id => /\d+/)
        get.named_route("edit_#{name.singularize}", "#{name}/:id/edit",  :action => 'edit', :id => /\d+/)
      end

      map.with_options :conditions => { :fb_sig_request_method => 'POST' } do |post|
        post.named_route("create_#{name.singularize}",  name,                  :action => 'create')
        post.named_route("update_#{name.singularize}",  "#{name}/:id",         :action => 'update',  :id => /\d+/)
        post.named_route("destroy_#{name.singularize}", "#{name}/:id/destroy", :action => 'destroy', :id => /\d+/)
      end

    end
  end

Pastie link

Notice the new :condition => { :fb_sig_request_method => 'GET'} and :condition => { :fb_sig_request_method => 'POST'}? That is the key we need to be able to overload a path like /entries/1 to call #show or #update depending on the condition. As a result, our routes now generate much nicer paths. Check it:

  GET    /entries            # index
  GET    /entries/new        # new
  POST   /entries            # create
  GET    /entries/1          # show
  GET    /entries/1/edit     # edit
  POST   /entries/1          # update
  POST   /entries/1/destroy  # destroy

A patch has been submitted to Facebooker. Hopefully the maintainers will see it fit to merge this in. As an added bonus, the patch also includes singleton resources via

  facebook_resource :entry

to generate the following routes:

  GET    /entry              # show
  GET    /entry/new          # new
  POST   /entry              # create
  GET    /entry/edit         # edit
  POST   /entry/update       # update
  POST   /entry/destroy      # destroy

Note that this is still very much a workaround until Facebook moves all the fb_sig metadata into the request headers and use real GETs and POSTs. But until then, happy programming!

Just a quick note that the blog will be down for maintenance at 1PM MYT. Barring no issues, it should be a quick 5 minute downtime.

As a startup, we have the opportunity to seed the company culture and process. This affects what tools we use to manage these processes. We are still experimenting with various tools, and I foresee there will still be a lot of changes in the near future. Nevertheless, I have listed down all the tools we are using to keep this ship sailing.

Tools we evaluated, but didn’t make the cut:

  • Retrospectiva for keeping track of our projects’ tasks and change sets. We stop using Retrospectiva because it does not have enough features to support our version of agile software development.
  • Acunote for tracking projects’ tasks. Acunote is an excellent tool. But we decided to switch to Rally due to more complete feature sets (bug tracking, estimate vs actual time comparison, etc). Free for teams of 5 and below.

Tools we are using now:

  • TextMate for Rails development.
  • SVN for versioning our source code.
  • Mac OS X for a rock solid platform. The ability to run Windows using Parallels or Fusion for cross-browser testing is a nice bonus.
  • Basecamp for tracking our administrative and non-coding tasks.
  • Apple iCal with WebDAV for sharing calendars internally.
  • StikiPad for our internal wiki.
  • Google Apps for email hosting.
  • Google Alerts for keeping tabs on what the web says about us and our products.
  • WordPress for all our blogging needs.
  • Amazon S3 for offsite backup and asset hosting.

Tools we have our eyes on:

  • Rally for managing our projects. Community Edition is free for teams of 10 and below.
  • Campaign Monitor for email lists management and marketing.

Most tools listed above are hosted and come with affordable pay-as-you-go or free plans. This frees the company from a lot of fixed costs and full-time maintenance effort so we can focus on building the next big thing.

What tools you use to run your startup?

We're Hiring
RSB is currently looking for Ruby On Rails developer and Web / Graphic Designer to join our amazing family.
Categories

Enter your email address:

Delivered by FeedBurner