Web services and some tips to share

API stands for Application Programming Interface.  I’m sure you wouldn’t be reading my post if you aren’t aware what it is.

From Wikipedia:

An application programming interface (API) is a source code-based specification intended to be used as an interface by software components to communicate with each other. An API may include specifications for routinesdata structuresobject classes, and variables.

– http://en.wikipedia.org/wiki/Application_programming_interface

I wouldn’t delve so much into what it is and what it isn’t, but I’ll got straight to describing what its pros and cons are in different business scenarios.  With this post, I have listed some of my own tips to share that could help you out in making good decisions for your product platform and implementation. Read more »

Dec 27, 2011 - Coderkitty, Ruby on Rails    No Comments

Ruby to the Rescue

A couple of days ago, I stumbled into the trouble of rounding up resumes and attachments.  There was a dump of all assets available from Amazon S3, and the files were organized according to folders and broken down by ids.  The task was simply to group them all into one folder.

Instead of wasting precious bandwidth, we had the initial file structure downloaded to an FTP site and was duplicated on a local machine.  Locally, manipulations were done to have all the files in one big folder.. via Ruby. Read more »

Capistrano Deploy sequence

Capistrano is really helpful in deploying applications. Its just basically one command line to execute. Writing the recipes themselves are also easy, but what’s not explicitly written is the sequence of which the deploy process goes through.

I’ve been fixing my cap scripts and having a hard time with rails 3 and thin. Hence, I needed to look for the sequence and hook up the right calls there. I found it here: http://theadmin.org/articles/2010/06/24/capistrano-deploy-sequence/

deploy
|-- deploy:update
|---- deploy:update_code
|------ Code update based on the :deploy_via
|------ deploy:finalize_update
|---- deploy:symlink
|-- deploy:restart

Just thought that noting it down again would help others too.

PS: This is also a good gem to consider: http://capitate.rubyforge.org/index.html

Apr 27, 2011 - Coderkitty    No Comments

What makes a developer successful?

These are my recent thoughts.

I have attended the RedDotRubyConf in Singapore, a couple of days ago. I realized, everyone in the room is successful. I also realized that everyone’s definition of success was rather very different.

When I was in Singapore, I met with a friend of mine who graduated from the same course as I did. We managed to have a long chat at Starbucks, Raffles Mall and made exchanges about our current jobs. She was working as a Tech Support in a big Singaporean company. She recently moved there and was assigned this position because her bosses felt that she was fitting for the role, since she had a very technical background. But this is not how she defined success.

She said that success was actually if and when she works not so hard in a nice company but earns a substantially good amount. Mine was totally different. And, I think that others who sat with me there in the Conference also had different views about their own successes.

I envied those who had the liberty of time as a freelancer because they were able to try on anything and anytime they wanted. Not being tied to a company made them able to soar higher than the rest because they are able to explore everything outside having a “job title”. However, they did have other concerns about their successes. Tenureship is one worry.

When I looked around, I felt that I have missed a lot about my techie world. Managing people and wanting to code is something else altogether. Handling difficult people is really another story altogether. Handling messy code and uncohesive process is I think trivial. There are many tools, and many tried on processes around. But who’s to say that doing so makes you successful?

In my humble opinion (IMHO- I just wanted to expand it to give it more gravity), being successful as a developer doesn’t lie on how many tools and languages you’ve actually come across with. Its not based on how many projects you’ve actually deployed it with, but the number of mistakes you’ve actually done. The number of consults you also make defines you as a learner.

I believe that learners, though they can be coined as “forever students”, holds the key to a brighter future. I hate the fact that people can’t be “told” or “injected” with ideas. We are always expanding. Everything is an opinion, until you have tried it and experienced it.

Bottom line, a successful developer is one that will always be moved, will always be shifted because he/she adapts to change and is always open to inputs. Be it from the intarwebz, the community one lives in, or even at work.

I wanna be able to solidify my statements with experiences. I want to experience the tools and the coding. I want to be successful.

Nov 19, 2010 - Agile & Scrum, Coderkitty    No Comments

Coderkitty attests to Scrums’ success

Last September 2 and 3, I was privileged to have been sent to an Agile Training at Sofitel. I met a lot of good people wanting to implement some change by promoting transparency and successful product iterations.

Scrum is not a new thing for me, but it was well worth it to strengthen what I already know and try to get some help from the scrum masters there too on some problematic situations I’ve encountered. It was fun, and I got to share some of my experiences too. Gained some friends in the process and enjoyed myself during the training. Found below is a photo of Franchere Chan, myself, and Allan Tan.

Franchere Chan, Myself and Allan Tan

Yukka Lindstrom and Emerson Mills were really good trainors and weren’t boring too! Emerson’s endless stream of stories to share helped in understanding what scrum practice would be and what it can’t be for a team, a project or a process.

Overdid myself again!

Attendees of the Certified Scrum Master training course range from software developers, programmers, and project managers of the IT industry’s leading companies who are looking to gain a deeper understanding of Scrum. According to attendees, many of their clients are either already using the methodology or are interested in using it with the goal of increasing productivity. The last training course was attended by such companies as Ideyatech, SQME Professional, ProV International, HP NexUS, and Macquarie. By far, Scrum seems to be getting good results, as Maricris Nonato of DevEx attests. “I think it’s working well for us,” she claims. “The turnaround of every sprint cycle is good. By far I haven’t had a failed sprint yet. And our stakeholders are happy. You know the transparency thing that scrum promotes is very helpful for them. Scrum is really working out for us.”

Read more here: http://codelean.com/en/News/10-09-27/Scrum_Practices_Gain_Popularity_in_the_Philippines.aspx

Visit Codelean to find out more about Scrummaster Training.

Picking up the breadcrumbs

Its always easy to skip going through the details of what your stacked up knowledge and just go for trying out new stuff. This time, I take it one step back and skim through pages of books I have always ignored and pick some sections that are worth looking into and post them here.

I’ve been trying to cut down on paper materials at home. Mostly, trying to read all those books and photocopied materials and just jot down notes from them. I decided to post them instead. So here goes..

From a photocopy of a ruby/rails book (no title gathered):

Some string extensions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
string = "Now is the time"
puts string.at(2)  #=> "w"
puts string.from(8)  #=> "he time"
puts string.to(8)  #=> "Now is th"
puts string.first  #=> "N"
puts string.first(3)  #=> "Now"
puts string.last  #=> "e"
puts string.last(4)  #=> "time"
 
puts string.starts_with?("No")  #=> true
puts string.ends_with?("ME")  #=> false
 
count = Hash.new(0)
string.each_char { |ch | count[ch] += 1 }  
#=> {" " => 3, "w" => 1, "N" => 1, "o" => 1, "e" => 2, "h" => 1, "s" => 1, "t" => 2, "i" => 2 }

Customizing inflections:

1
2
3
4
5
Inflector.inflections do |inflect|
  inflect.plural(/-in-law$/, "s-in-law")
  inflect.singular(/s-in-law$/, "-in-law")
  inflect.uncountable("air", "information", "water")  #no singular form, no plural form
end

Extensions to numbers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
puts 3.ordinalize  #=> "3rd"
puts 321.ordinalize  #=> "321st"
 
puts 20.byes  #=> 20
puts 20.kilobytes  #=> 20480
puts 20.megabytes  #=> 20971520
puts 20.gigabytes  #=> 21474836480
puts 20.terabytes  #=> 21990232555520
puts 20.petabytes  #=> 22517998136852480
puts 1.exabyte  #=> 1152921504606846976
 
puts 20.seconds  #=> 20
puts 20.minutes  #=> 1200
puts 20.hours  #=> 72000
puts 20.days  #=> 1728000
puts 20.weeks  #=> 12096000
puts 20.fortnights  #=> 24192000
puts 20.months  #=> 51840000
puts 20.years  #=> 630720000
 
puts Time.now  #=> Tue May 18 22:03:21 +0800 2010
puts 20.minutes.ago  #=> Tue May 18 21:43:53 +0800 2010
puts 20.hours.from_now  #=> Wed May 19 18:04:11 +0800 2010
puts 20.weeks.from_now  #=> Tue Oct 05 22:04:22 +0800 2010
puts 20.months.ago  #=> Thu Sep 18 22:04:34 +0800 2008
puts 20.minutes.until("2010-12-26 12:00:00".to_time)  #=> Sun Dec 26 11:40:00 UTC 2010
puts 20.minutes.since("2006-11-08 01:15:00".to_time)  #=> Wed Nov 08 01:35:00 UTC 2006

Time and Date Extensions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
now = Time.now  
puts now  #=>  Tue May 18 22:09:17 0800 2010
puts now.to_date  #=> 2010-05-18
puts now.to_s  #=> Tue May 18 22:09:17 +0800 2010
 
puts now.to_s(:short)  #=> 18 May 22:09
puts now.to_s(:long)  #=> May 18, 2010 22:09
puts now.to_s(:db)  #=> 2010-05-18 22:09:17
puts now.to_s(:rfc822)  #=> Tue, 18 May 2010 22:09:17 +0900
puts now.ago(3600)  #=> Tue May 18 21:09:17 +0800 2010
puts now.at_beginning_of_day  #=> Tue May 18 00:00:00 +0800 2010
 
puts now.at_beginning_of_month  #=> Sat May 01 00:00:00 +0800 2010
puts now.at_beginning_of_week  #=> Mon May 17 00:00:00 +0800 2010
puts now.beginning_of_quarter  #=> Thu Apr 01 00:00:00 +0800 2010
puts now.at_beginning_of_year  #=> Fri Jan 01 00:00:00 +0800 2010
puts now.at_midnight  #=> Tue May 18 00:00:00 +0800 2010
 
puts now.change(:hour => 13)  #=> Tue May 18 13:00:00 +0800 2010
puts now.last_month  #=> Sun Apr 18 22:09:17 +0800 2010
puts now.last_year  #=> Mon May 18 22:09:17 +0800 2009
puts now.midnight  #=> Tue May 18 00:00:00 +0800 2010
puts now.monday  #=> Mon May 17 00:00:00 +0800 2010
 
puts now.months_ago(2)  #=> Thu Mar 18 22:09:17 +0800 2010
puts now.months_since(2)  #=> Sun Jul 18 22:09:17 +0800 2010
puts now.next_week  #=> Mon May 24 00:00:00 +0800 2010
puts now.next_year  #=> Wed May 18 22:09:17 +0800 2011
puts now.seconds_since_midnight  #=> 79757.033881
 
puts now.since(7200)  #=> Wed May 19 00:09:17 +0800 2010
puts now.tomorrow  #=> Wed May 19 22:09:17 +0800 2010
puts now.years_ago(2)  #=> Sun May 18 22:09:17 +0800 2008
puts now.years_since(2)  #=> Fri May 18 22:09:17 +0800 2012
puts now.yesterday  #=> Mon May 17 22:09:17 +0800 2010
 
puts now.advance(:days => 30)  #=> Thu Jun 17 22:09:17 +0800 2010
puts Time.days_in_month(2)  #=> 28
puts Time.days_in_month(2, 2000)  #=> 29

Extension to Ruby Symbols:

1
2
3
4
5
groups = posts.group_by { |post| post.author_id }
 
or
 
groups = post.group_by(&:author_id)
Feb 25, 2010 - Agile & Scrum, Coderkitty    No Comments

Acknowledging the unknown as part of the process

I think this is by far the best, though vague and ambiguous poetry I’ve ever seen and I loved it!

It puts the technical context of programming in a development cycle into lay context. :) I stumbled upon this lovely piece of work, through CodingHorror’s article entitled: Version 1 Sucks, But Ship It Anyway

As we know,
There are known knowns.
There are things we know we know.
We also know
There are known unknowns.
That is to say
We know there are some things
We do not know.
But there are also unknown unknowns,
The ones we don’t know
We don’t know.

Makes me want to keep in mind that knowledge in programming is quite volatile as it comes to real world problems to be solved, and that no accurate solution is definite across a period of time. The unknown is really a part of the process.

The power of toggle

I don’t know if we’ve been missing out on deliberate API lovin’ or that we’re becoming dumber every minute because of too much work, or its just the love month? :) …but we’ve been missing the power of “toggle“.

Toggle is defined as:

any instruction that works first one
way and then the other; it turns
something on the first time it is used
and then turns it off the next time

Needless to say, toggle is very efficient for use with boolean values (defined by either true or false). Let’s take a specific scenario:

1
2
3
4
5
6
7
8
9
10
11
12
  create_table "profiles", :force => true do |t|
    t.string   "salutation",            :limit => 8, :default => ""
    t.string   "name",                  :limit => 200, :default => ""
    t.datetime "created_at"
    t.datetime "updated_at"
  end
 
  create_table "themes", :force => true do |t|
    t.integer "profile_id",
    t.string   "name",            :limit => 100, :default => ""
    t.boolean "primary",        :default => false
  end

So, there are multiple themes per profile. You should get at least that part. Your boolean column should always be set to false by default. Either you replace the name of your column to suit that requirement, or write dirtier code. (I.e., instead of have a “public” column all set to true, use “private” column all set to false by default). Now, of course, your associations should be setup properly similar to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Profile < ActiveRecord::Base
 
  # filter_chain methods here...
  # validations here...
 
  # associations start...
  has_many :themes do 
    def primary
      find(:first, :conditions => ["primary = ?", true])
    end
  end
  # associations end...
 
end
 
class Theme < ActiveRecord::Base
 
  # filter_chain methods here...
  # validations here...
 
  # associations start...
  belongs_to :profile
  # associations end...
 
  named_scope :current_theme_of, lambda { |profile|
    { :conditions => [ "profile_id = ? and primary = ?", profile.id, true ] }
  }
end

Of course, there would be several records for the Theme table that will belong to a profile. You will offer a checkbox on every create and update of the themes of a particular profile, but how do you ensure that there will only be one primary theme set for each profile record?

This is dirty: (KIDS, DO NOT TRY THIS AT HOME)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Theme < ActiveRecord::Base
 
  # filter_chain methods here...
  after_save :verify_unique_primary_theme
  # validations here...
 
  # associations start...
  belongs_to :profile
  # associations end...
 
  named_scope :current_theme_of, lambda { |profile|
    { :conditions => [ "profile_id = ? and primary = ?", profile.id, true ] }
  }
 
  def verify_unique_primary_theme
    # get all themes by this profile 
    # set all their primary value to false
    # set this new one's primary value to true
  end
end

Man, I wouldn’t bet on a quick update on a profile whose set of themes would be more than hundreds, or even thousands! This, of course, is always worth a try:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Theme < ActiveRecord::Base
 
  # filter_chain methods here...
  # validations here...
 
  # associations start...
  belongs_to :profile
  # associations end...
 
  named_scope :current_theme_of, lambda { |profile|
    { :conditions => [ "profile_id = ? and primary = ?", profile.id, true ] }
  }
 
  def primary?
    primary
  end
 
  def validate
    #ensure that primary true is for one record only
    if primary? and !profile.themes.primary.nil?
      #toggle the old primary theme of this said profile
      profile.themes.primary.toggle!(:primary)
    end
  end
 
end

Simple, yet it works! Each time another theme gets toggled to be the primary theme, you only need to make two writes to your database:

  1. Save your new item
  2. Flip the old primary to false

PS: I did write messy code on purpose to illustrate what I meant for this post.

I hope this toggle magic works for you too the next time you think about boolean switches!

:)

DIY Ruby SFTP to S3

I was faced by a challenge of transferring some files from an FTP server to S3. At first, the nature of the problem seemed simple. I just had to get the files to my local machine and then upload them to S3. Piece of cake! But lo and behold, when I saw that there were over 32K files and each step took me almost 2 minutes each! Oooh lala!

I knew this was a job for fanfare sound here the almighty ruby! :)

And so, I set my priorities straight.. I had to work elegantly and save time altogether. I’m feeling quite exhausted and would really love to get some sleep soon, so here I am, depending on my great yet simple ruby skills and the power of ruby itself to help me achieve this task!

As I write this article, my script is silently running in the background as a very obedient and competent slave. :P But to help you out, here is a brief guide on how to sit back, relax and let the task be accomplished in no time! You should really be sending me gifts.. or better yet, donate to me via Paypal! I’ll love it, I promise.. I might even give you a page of exposure! :)


So, here’s the deal. You have a set of files to download via FTP and a particular folder structure where you want it to go.

STEP 1:

Gather your FTP credentials as follows:

1
2
3
4
host: my.server.com
username: my_username
password: my_password
port: 12345

STEP 2:

We will need some gems here. Now, if you don’t have them yet, now is a good time to install them:

1
2
sudo gem install net-sftp
sudo gem install fastercsv

Net-Sftp is needed for the communication to your FTP server. You can use this even if your access is just set to anonymous. You might want to use another CSV parser if you want, or if you already have something else in mind. You can just tweak the code for that section.

STEP 3:

Now, pull out your beloved spreadsheet editor (mine is OpenOffice) and aggregate your data.

Full remote path to the files Full local path to save into
/your/ultra/deep-stack/of/remote/folders/path/to/filename.doc /Users/coderkitty/attachments/not-so-deep-stack/filename.doc
/your/ultra/deep-stack/of/remote/folders/path/to/filename2.doc /Users/coderkitty/attachments/not-so-deep-stack/filename2.doc
/your/ultra/deep-stack/of/remote/folders/path/to/A super special filename here.doc /Users/coderkitty/attachments/not-so-deep-stack/itsnolongerspecial.doc

STEP 4:

With this, you should export your file to CSV format and remove the Text Delimiter setting.

Export

Export

STEP 5:

Open your CSV file using your favorite text editor (mine is TextWrangler, you might want to try it. Its opensource and free). Make sure that all spaces in your filenames are escaped properly, so that you have something like this:

1
/your/deep-stack/of/remote/folders/A super special filename here.doc

changed into:

1
/your/deep-stack/of/remote/folders/A\ super\ special\ filename\ here.doc

then don’t forget to save your csv file.

STEP 6:

Now, this is a fork. You have two (2) choices you can take. Either one works fine. Just pick your desired approach.

  • Save the remote path and the local path in two separate csv files for loading (version 1), or
  • Use one big csv file of remote, local path (version 2)

STEP 7:

The rest is quite straightforward from this point onwards. Just fill in your constants in the ruby script and then make sure that your files are in the right directories. All set? Execute away!

1
ruby sftp_to_local.rb

You might also find that the generated errors.txt file could help you reiterate on some parts of downloading/uploading your file. Sometimes your path could be wrong, or that you forgot to specify the correct local directory.

STEP 8:

Now, your files should be created in your machine. Now what? For this, you will need the handy-dandy S3Fox. Get it here: http://www.s3fox.net/ Launch the tool from your browser. Now, you can simply sync your folders from your machine to your S3 buckets. Its as easy as that!

STEP ???:

Grab your favorite coffee and wait for the script to complete. Try to sleep for awhile, watch a movie, maybe give me a tip?


PROFIT!!!!

Check your buckets after some time and enjoy the presence of your easily uploaded files. :)

Pages:123»
  • Facebook
  • LinkedIn
  • FriendFeed
  • Twitter
  • Tumblr
  • Flickr
  • YouTube
  • Vimeo