Search This Blog

November 25, 2011

Prevent rails from pluralizing table names

In the Database world, it is the convention for the table names to be singular. Rails irks the pure DB-folks by pluralizing table names. In my previous project, the DBA was terribly upset with the pluralized table names that was created because of Rails and was hell bent on singularization of the table names. I won't blame him for that. In fact, I support it.

But know what Rails is an awesome framework, you can ensure that the table names are not pluralized with a single configuration line in your project's environment.rb file.


Rails 3 and its Sandbox


Rails console has always been a friend in need for the Rails developer. More often, we get to the console to try out some coded snippets to verify and validate our assumptions, either while writing the test cases or during the coded implementation. In this process it is very likely that we end up modifying the state of the underlying database. This inturn can cause some headaches or frustration. Nonetheless you soil the database with junk data. If you are fine with it, then read no further - this post is not for you. If however you are wondering for a way to SANDBOX your play environment from soiling the database, then read on.

Run your console with the command as below:
$ rails c --sandbox 
That is all you need to do to maintain the sanity of your undedrlying database.

So what does this sandboxing do? It keeps journaling all the activities that you do on the database and will undo it all upon exit so that the database goes back to the state previous to sandboxing. 

There are some implications however to working this way though. If you were to run the sandbox on say, development database, then you wouldn't be able to run your DB migrations on your database while the --sandbox is on. Oh!, in fact you wouldn't be able to modify the state of the databases in any manner, be it insert / update / delete records. When you attempt to do it, you would see that the DB throws an error message that reads something as below: 
ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: ...

November 19, 2011

Miniature Code Retreat


I was so excited with the idea of Code Retreat invented by Corey Haines, that I pushed for conducting a miniature version it (with just two sessions of pair-programming) at Dev Camp Chennai, 2011.

My Goal of conducting a Mini Code Retreat
  • First and foremost, my agenda was to market the Global Code Retreat that is to happen on the December 3rd of 2011. 
  • There are very few corporates that follow TDD, pairing and "refactoring". If folks who can participate in the session, get a good hang of and appreciations for it all, then they would well become agents to market the experience of good practices.
  • Its been a long while since I facilitated. I personally wanted to see where I stand in facilitation and see what I derive out of this session as a facilitator.

What I did to achieve my goals
  • Dev Camp was a good crowd puller and I wanted to use that occassion to ensure that I give people the taste of what really Code Retreat is all about. Soon after my welcome address, I did a quick poll of how many know of the Code Retreat event that is to happen two weeks from now and then gave an introduction to Code Retreat (early marketing). 
  • Kept reading different blog posts etc sharing the code-retreat conduct and facilitation experience, lessons etc.
  • Not many folks had a laptop with them in the DevCamp. This was really unfortunate. Made an announcement that only folks with laptop have a entry pass, to the code retreat event. This sort of disappointed the really interested few, some of whom approached me post my introduction. Touched by the enthusiasm, I had arranged for three laptops with the required things setup.
  • In the very beginning, I decided to pair-up with someone who is very earnest and equally passionate as much as I was. And I did pair-up with my friend and fellow comrade Ponnulingam, who did all the work that is required to ensure that the laptops are all set-up with necessary SDKs, IDEs, base project set-up with a unit-testing framework.
  • At the start of the code retreat session , we set the ground rules, the dos and the don'ts. 
  • Gave the classical Mars Rover problem of ThoughtWorks Recruitment to attendees. I choose this problem (with the due permissions from the Recruitment team's lead, Manish), over anything else because the problem is very straightforward. This gives the coders a good opportunity to focus on the ground rules, pair-programming experience, TDD approach and stuff, instead of being distracted to spend endless time discussing the problem statement. Though honestly, I realized they were trying to the same until I was parroting the mantra a few times to stop discussing too much of details, and start coding ASAP after the first 3 minutes. In 5 minutes time, every one started coding.
  • Swap pairs after every round.
  • Conduct of retrospective at the end of the session helped folks to learn from others goodness/mistakes. It gave them a renewed sense of energy and interest.

Results
  • In just two session, it was nice to hear from folks who experienced the joy of TDD (test first/driven development).
  • Everyone but for just a single pair weren't comfortable pairing in every session. Interestingly enough, the pairs that reported this were entirely different. I realized in in both these occassions, one of them took things very personally by their stride, and also that they broke the very basic ground-rule of deleting the older coded (the pair that had written the code hung to it and was trying to enforce the further development on the existing code). I wish, I had caught this while I was moving from pair to pair to check on what they do - good and bad, by the time I reached this pair I was only thinking that they had progressed that far.
  • As pair facilitators, we decided to rope in another pair to help us out in facilitation, and that really helped. I believe understanding the maturity/skills level of coders is very very important for better facilitation. If the majority find the terms - TDD, pair-programming, refactoring - very new but something that they have heard of and are extremely curious to know it all in one gulp, you need more folks who could get them settled quickly.
  • Many felt that they were better able to understand the problem statement as result of pairing.
  • There were a few who felt that while at the very beginning they were not so comfortable pairing with experience programmers, became very confident by the end of the session as result of picking up skills from their experienced peer and practice it in their presence while pairing.
  • Most of them felt pairing increased their productivity, because they weren't lost in their thoughts and thinking out loud with their pair benefitted them clearly.
  • Folks left the room with a sense of enlightened joy, saying they would come again to experience the learning again at Code Retreat.
  • In second round, good half of the coders became self-disciplined to TDD. I find this interesting.
  • We concluded the Code Retreat with a retrospective, in which we asked people to provide anonymous feedback on their experience of the Code Retreat session in entirity. We split the board into three pies - "What went well?", "What didn't go well", "Puzzles". Once everyone left, my curius eyes went to the Not-well section and found just TWO single-worded sticky(s) with "nothing" scribed in it. Not sure if they meant, there was nothing that didn't go well or that they have gained nothing which isn't well. I read it as the later.
Feedback Received
Pictures of the Code Retreat session can be seen here.

November 12, 2011

Agile Tour 2011, India


Agile Tour 2011, India @ Chennai on 12-November-2011

I had the opportunity to give two extempo lightening talks to the people at this conference. The topics were, "The attitude that an individual and team has to carry when the CI build breaks" and "Planning is important but plans are not". I felt compelled to share my experience and thoughts on those topics,  because I observed that the delegates were discussing about it more and wanted more clarity.

How my talks were received?

Oh I guess, it was well received as many could understand and appreciate it prompting them to talk and ask more questions about Agile post my talks. I doubly enjoyed it, because there were both developers and management folks equally interested to learn more and more by way of discussing things in their mind with me.

Secondly, Preethi Madhu, ThoughtWorks India, Head of Consulting, was happy to provide a very positive feedback to me. Thanks Preethi :)

May I request your feedback on my talks?

If you have attended/participated-in my talk and discussions thereafter,...and have something to share, then please feel to put yout thoughts across by way of comments to this blog post.

Also, if you have published any photographs of the event, please do share them in the comments section and I shall make a reference to it all by posting the links in this blog post.


My views on the overall event

I appreciate Madhur Kathuria (CSC, Product Operations Manager, PegaSystems) and his team, for hosting and organizing the event in a manner that is conducive for open discussions/learnings and for the impromptu lightening talks and open-space event -if it is not for this, the delegates wouldn't have recognized the speaker in me!.

If at all there is something I would wish, it would be that there was a video recording of the session. I would have loved to publish my talks in my blog post :P

Update: The pictures of the even can be found in FaceBook.

October 30, 2011

Vim for Rails Developer


Every person gives feedback based on his understanding of things which is dependant on his level of skills at that point in time. For the reader of this post, who is interested in knowing my background to better evaluate my feedback, I have elaborated in brief my history of experience in the RoR world of application development.

After spending about 10 months in my first JRuby on Rails-2,  two-developer all-chaotic first non-pairing project, where I was using RubyMine as IDE for all practical development purposes, I resolved to try out a new IDE in my next Rails gig. Folks at ThoughtWorks are in the habit of experimenting and trying out different IDEs. And hey, I was no exception ;) - prior to RubyMine, I tried Vim and Aptana RadRails, but for whatever reason I loved RubyMine, perhaps because I was too familiar with this one by virtue of my experience of using IntelliJ in Java projects.

As decided I did choose a new IDE when I moved on to my second RoR3 gig and it was Vim. Why Vim? Well, apart from it being extremely lightweight when compared to its counter-parts, I seriously wanted to get a hang of this IDE, as many RoR developers at our office either use TextMate or Vim (by stats more Vim fans). Okay so did I step into this very small and demanding project of just two developers (including me) that were notably enough not pairing (again!). What does that mean? It means I have to constantly explore to figure out the stuff that is required to become more and more conversant and productive with Vim (atleast as much I am with RubyMine). If you have gone through my experience you'll understand how steep a learning curve it is to get an appreciation of Vim for Rails productivity (even while learning Rails 3, argh!).

Now, I have moved on to my third RoR3 gig with 3-4 dev-pairs (ho-ho pairing again, after real long time!), where-in I guess all are Vim-ites. Its been a couple of days, and I see people use many productive plugins for Vim. Delighted!, my learning curve is going to get better.

In the mean time, I had requested Ben Orenstein, for a free copy of screen cast titled, "Vim for Rails Developers" that he authored. In return, I promised to write a candid review of his screen cast on my blog. I fulfill my promise with this blog post wherein I share my thoughts/experience of the said screencast. Now, the way I share my thoughts is by dissecting the portions of screen cast, and tell you what to expect from each of it. [pause] So, in the mentioned screencast, Ben has covered the following sections in bold:

Fast Typing:
  • Do you think, 80 words per minute is okay? Listen to him.
  • play.typeracer.com => How this site helps the enthusiast hit Bens's objective of "Speed with ********"

Vim Cheat sheet:
  • viemu.com => I have many a times visited and downloaded this cheat-sheet from this site, but didn't really care to read it seriously. His talk I guess insisted well on what to look out for in this cheat sheet :)

Dvorak Simplified Keyboard
  • Learn to touch type.
  • I haven't heard this anytime before. I gotta know about this in this screen cast.
  • This is the only section that did not fascinate me, perhaps because I did not see him demonstrate its usefulness.

Rails.vim
  • An intro on how to use it. He gave a real good shot at it, helping me understand that he did his best given the size of this huge plugin. Keep digging and you get more and more wealth of short-cuts! 
  • If you haven't used this plugin, his intro will seed the interest in you to try and have fun with this plugin.
  • Try this in your Vim command-line: :help rails => for rails-vim documentaion          

Snipmate: Mac's Textmate style snippets for Vim
  • It supports Rails
  • Where to look for your favorite language's snippets that snipmate supports [Note: ~/vim/snippets/]                
  • How to add your own snippet

The power of Tags
  • Exuberant CTAGS: CTags creates an index on where the class, methods, instances are defined. This helps the developer big-time in jumping from say, method usage to its definition. Intelli-sense of sorts, eh!
  • How to use CTags?
  • How CTags help?

Ack
  • Get it right. Its Ack, not awk! Its a grep replacement tool, designed for programmers. Can't believe the funda? Well, I too didn't until I watched him play in this screencast.

Quick one-offs    
  • Bunch of other enlightening surprises... :) By the time you reach here, you won't feel like skipping this section, for you'll quickly come to an understanding that this is not some miscellaneous stuff but the quick wins that you get to learn while you are playing with Vim.

For many, "seeing is believing". And I fall very much in that category. Thus, this screencast had a very good impact on me and so shall it on you ;) You can't ask for more in a screencast that is approximately 37 minutes long.

I'll heartily give him a 4.5/5 as rating for this screencast, for the good breadth and fair depth in content that he has both covered and demo-ed, in a manner that inspired me to kick myself harder to learn and get used to the stuffs/tools that he mentioned.

Thanks to Ben, for an awesome introduction through live demo to the various tools that he uses for his every-day rails programming. Personally though, I wish wish wish, he touched upon the other productivity plugins too, if he were to use any. Don't know if I'm being greedy here!

Lastly, if you wish to watch this screen-cast, and that you are put up in Chennai, don't miss the DevCamp,Chennai happening this November 19th at ThoughtWorks Technologies Ltd, Ascendas IT Park, Chennai, Tamil Nadu, India. This screencast is making an entry, and if voted for by many (as like any other in-person session), it will be put up. Come vote, watch and get enlightened!

October 21, 2011

Leveraging Subject in RSpec - A rough cut!

Do you use subject in RSpec? This blog post intends to help you get better with RSpec's subject. The better way to learn things is by way of an example; even better if we see a bad example and see how we can progressively improve it.



The better way to write the above test is as below:



Further refactoring the above code snippet, it can be compacted to below, although I hate to do this. I prefer to tests/specs being an utter no-brainer to read quickly and get the idea:



Finally the ideal way of testing the above scenario and the like would be to employ RSpec's subject as below:



If after reading all this you were to wish it be more leaner, then you should consider shoulda. Will blog about it's marriage with RSpec sooner ;) Until then see how snappier the above code becomes with the use of shoulda matchers. Hooray!!!


SQL Logging in Rails Console IRB


In order to quickly find the SQL queries that are fired against the DB, while you are playing on the Rails Console, all you need to do is set ActiveRecord's Logger to STDOUT as below:

>>ActiveRecord::Base.logger = Logger.new(STDOUT)

Custom finders and SQL Injections

Everyone writes bad code. The most awful and potentially very dangerous ones that cannot just cannot sit in the commit-able code are the badly written raw SQL queries or even your API code that can give leeway to SQL Injections or SQLi.



[ERROR] couchapp error: You aren't in a couchapp.


Every CouchApp must have a .couchapprc file in the application directory. This file is a JSON object which contains configuration parameters that the command-line app uses to build and push your CouchApp.

The couchapp generate and couchapp init commands create a default version of this file for you.

If you don't have a .couchapprc file, couchapp will display the dreaded couchapp error: You aren't in a couchapp message.

September 21, 2011

Can't find first MyFreakingActiveRecordModel

Can't find first MyFreakingActiveRecordModel.... Do you get this weird sounding error on running your spec for the model? A re-look at the exception should give you some cues. Yeah, it only implies that you don't have a test record for that model in your test environment DB. All you need to do is add a test record to the test DB. If you are using FactoryGirl, and RSpec, the code snippet below shows the way it can be done elegantly.


Lesson: Shoulda requires a record in the DB, well atleast in this case :P

September 6, 2011

Rails 3 - Filtering Sensitive Parameters From Being Logged

If you are wondering, "How on earth do I ensure that sensitive parameters are not logged anywhere by the Rails 3 application?". Well, its a cinch as far as Rails goes. All you need to do is add all your sensitive parameters to filter_parameters list in config/application.rb file.

A sample Rails3 config file having this setup will look as below (MyRails3App is the name of my rails application):

September 3, 2011

Untrack a file in Git

git rm --cached <file> 

The good thing about this command is that it will merely remove the file from the history tracking index. The local copy of the file will not be removed.

The story in detail...learning by experience


[practice]$ mkdir myproject
[practice]$ cd myproject/
[myproject]$ git init
Initialized empty Git repository in /home/karthik/MyRubyProjects/practice/myproject/.git/
[myproject(master)]$ git st
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)

[myproject(master)]$ touch abc.txt
[myproject(master)]$ git st
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add
..." to include in what will be committed)
#
# abc.txt
nothing added to commit but untracked files present (use "git add" to track)

Situation 1: If you were to untrack a newly created file that you added to staging for commit.

[myproject(master)]$ git add abc.txt

[myproject(master)]$ git st
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached
..." to unstage)
#
# new file: abc.txt

[myproject(master)]$ git rm --cached abc.txt
rm 'abc.txt'

[myproject(master)]$ git st
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add
..." to include in what will be committed)
#
# abc.txt
nothing added to commit but untracked files present (use "git add" to track)

I now guess we are on the same page on untracking of the addition of a newly created file in Git. Let us now go ahead to add this file back and commit it to repository. This will help us gear up for the next situation - Situation 2.

[myproject(master)]$ git add .
[myproject(master)]$ git st
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached 
..." to unstage)
#
# new file: abc.txt

[myproject(master)]$ git commit -m "Commit abc.txt"
[master (root-commit) a67174c] Commit abc.txt
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 abc.txt
[myproject(master)]$ git st
# On branch master
nothing to commit (working directory clean)
 


Situation 2: If you were to untrack an old file that has already been committed.

[myproject(master)]$ echo "sample text" > abc.txt
[myproject(master)]$ git st
# On branch master
# Changed but not updated:
# (use "git add
..." to update what will be committed)
# (use "git checkout --
..." to discard changes in working directory)
#
# modified: abc.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

[myproject(master)]$ git rm --cached abc.txt
rm 'abc.txt'

[myproject(master)]$ git st
# On branch master
# Changes to be committed:
# (use "git reset HEAD
..." to unstage)
#
# deleted: abc.txt
#
# Untracked files:
# (use "git add
..." to include in what will be committed)
#
#
abc.txt



With that result, let us call it a day ;)

June 22, 2011

Kill process listening/bound to specific port


Step 1: Identify the process
    For this you can use either of the command below:
lsof -w -n -i tcp:<port_number>
where,
-w implies suppression of warning messages
-n option inhibits the conversion of network numbers to host names for network files. Inhibiting conversion may make lsof run faster. It is also useful when host name lookup is not working properly.
-i[i] option selects the listing of files any of whose Internet address matches the address specified in i. If no address is specified, this option selects the listing of all Internet and x.25 (HP-UX) network files.
      If -i4 or -i6 is specified with no following address, only files of the indicated IP version, IPv4 or IPv6, are displayed. (An IPv6 specification may be used only if the dialects supports IPv6, as indicated by "[46]" and "IPv[46]" in lsof's -h or -? output.) Sequentially specifying -i4, followed by -i6 is the same as specifying -i, and vice-versa. Specifying -i4, or -i6 after -i is the same as specifying -i4 or -i6 by itself.
    Multiple addresses (up to a limit of 100) may be specified with multiple -i options. (A port number or service name range is counted as one address.) They are joined in a single ORed set before participating in AND option selection.
      An Internet address is specified in the form (Items in square brackets are optional.):
      [46][protocol][@hostname|hostaddr][:service|port]
      where:
            46 specifies the IP version, IPv4 or IPv6 that applies to the following address. '6' may be be specified only if the UNIX dialect supports IPv6.  If neither '4' nor '6' is specified, the following address applies to all IP versions.

            protocol is a protocol name - TCP or UDP.

            hostname is an Internet host name.  Unless a specific IP version is specified, open network files associated with host names of all versions will be selected.

            hostaddr is a numeric Internet IPv4 address in dot form; or an IPv6 numeric address in colon form, enclosed in brackets, if the UNIX dialect supports IPv6.  When an IP version is selected, only its numeric addresses may be specified.

            service is an /etc/services name - e.g., smtp - or a list of them.

            port is a port number, or a list of them.

Sample Command Line Output:
karthik@cloud:~/MyRubyProjects/dashboard$ lsof -w -n -i tcp:3000
COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ruby    2969 karthik    5u  IPv4  68913      0t0  TCP *:3000 (LISTEN)

Alternatively, you may use the command below:
netstat -anp | grep :<port_number>
where,
-a displays all active connections and the TCP and UDP ports on which the computer is listening.
-n displays active TCP connections, however, addresses and port numbers are expressed numerically and no attempt is made to determine names.
-p Linux: Process : Show which processes are using which sockets (similar to -b under Windows) (you must be root to do this)

Sample Command Line Output:
karthik@cloud:~/MyRubyProjects/dashboard$ netstat -anp | grep :3000
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      2969/ruby    

Step 2: Kill the process

kill -9 <procecss_id_number>

Eg:
karthik@cloud:~/MyRubyProjects/dashboard$ kill -9 2969

June 20, 2011

When you see Gem error like - "'': uninitialized constant Gem::SilentUI (NameError)"


I just created a new Rails 3 project called dashboard and tried having bundler install all the required basic gems for this project using the command - bundle install. Damn!, I got the error that is the title for this blog post.
Below is the snap shot of the command and the error:

karthik@cloud:~/MyRubyProjects/beach_projects/dashboard$ bundle install
/home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/ui.rb:56:in '<class:UI>': uninitialized constant Gem::SilentUI (NameError)
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/ui.rb:2:in `<module:Bundler>'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/ui.rb:1:in `<top (required)>'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/cli.rb:16:in `initialize'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/vendor/thor.rb:246:in `new'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/vendor/thor.rb:246:in `dispatch'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/lib/bundler/vendor/thor/base.rb:389:in `start'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/gems/bundler-1.0.7/bin/bundle:13:in `<top (required)>'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/bin/bundle:19:in `load'
from /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3/bin/bundle:19:in `<main>'

What is the issue? The issue is perhaps with the version of bundler and its dependencies. To resolve this issue, I ran the gem update for the bundler and know what? It worked ;)
Below is the snap shot of the command and the output:

karthik@cloud:~/MyRubyProjects/beach_projects/dashboard$ gem update bundler
Updating installed gems
Updating bundler
Fetching: bundler-1.0.15.gem (100%)
Successfully installed bundler-1.0.15
Gems updated: bundler


After this I tried running the "bundle install" command and the required gems were installed successfully.
Below is the snap shot of the command and the output:

karthik@cloud:~/MyRubyProjects/beach_projects/dashboard$ bundle install
Fetching source index for http://rubygems.org/
Installing rake (0.9.2) 
Using abstract (1.0.0) 
Using activesupport (3.0.3) 
Using builder (2.1.2) 
Installing i18n (0.6.0) 
Using activemodel (3.0.3) 
Using erubis (2.6.6) 
Installing rack (1.2.3) 
Installing rack-mount (0.6.14) 
Installing rack-test (0.5.7) 
Installing tzinfo (0.3.28) 
Using actionpack (3.0.3) 
Using mime-types (1.16) 
Using polyglot (0.3.1) 
Using treetop (1.4.9) 
Installing mail (2.2.19) 
Using actionmailer (3.0.3) 
Installing arel (2.0.10) 
Using activerecord (3.0.3) 
Using activeresource (3.0.3) 
Using bundler (1.0.15) 
Using thor (0.14.6) 
Using railties (3.0.3) 
Using rails (3.0.3) 
Using sqlite3 (1.3.3) 
Using sqlite3-ruby (1.3.3)
Your bundle is complete! It was installed into /home/karthik/.rvm/gems/ruby-1.9.2-p0@rails3

Reference:

Happy bundling :P

June 17, 2011

How to find the method definition - one that is invoked at runtime?


During the QnA session after my talk at RubyConf India 2011, one avid Ruby enthusiast asked me a question, "How to find the method definition - one that is invoked at runtime?".

I confessed that in all my experience (for the last eight and odd months) with Ruby, I have been doing the grep-ing for the method name and then figure out which method definition would be the last to over-ride every other ones declared earlier. No sooner did I finish answering, boooooooooom came a greatly handy tip from a very respectable and renowned geeky person in the crowd - Ola Bini. He adviced to use Ruby's "method" method to figure out the source of the method that was invoked at runtime. What an easier and neater approach!

Hearty thanks to both the folks - one who questioned and the other who answered.

This blog post is my attempt to elaborate more on the tip that Ola Bini had adviced.

Back home after the conference, I googled on these lines and found the following resources useful (in fact, this blog post is only my assimilation of these). May you find them useful.

Additional resources of interest:

June 7, 2011

Ruby Conf India 2011


I happened to be one of the speakers in this international conference that was held at Bangalore. What pleasure and privilege! The subject of my talk was Deciphering the Ruby Object Model, aimed to help fellow ruby enthusiasts level up their understanding and appreciation of Ruby as a programming language. The talk was well received by many a folks who had attended my session. I wish to thank every one who had personally come over to me for sharing their feedback with me.

You can download the presentation from any of the below mentioned locations:
Once the conference videos are published, I'll be glad to add its link here ;) Okie, it is now published, so please find it below:


Deciphering The Ruby Object Model from Innovation & Technology Trust on Vimeo.
For all the positive feedback I had received, I intend to very soon publish a couple of blog posts detailing on specific areas of interest. If you have attended my talk and wish I write up a blog post or two on specific areas please do feel free to communicate it via comments to this blog post and I shall make my humble and sincere attempts to dispell some of the confusion and enlighten you in that area.

Any other feedback that you would like to share is also welcome ;) You may always use the comments section of this blog for this purpose.

A few sites or blog posts that did have a mention of my talk or appreciations/criticism for my talk are put listed below. They'll be my motivation to move forward - further and faster!

Some live tweets while I was delivering my talk can be found below:






As I have mentioned in my talk, the following books should be a part of your reading book-shelf if you are serious about programming in Ruby:


   

May 7, 2011

... the gem has no specification file. Run 'rake gems:refresh_specs' to fix this.


Did you happen to vendorized gem and get a warning message like, "... the gem has no specification file. Run 'rake gems:refresh_specs' to fix this."? Afterr looking at the warning message did you try running the suggested rake command - rake gems:refresh_specs - to no avail? What next? How the heck do I get rid of this warning message?

Well, in times when gems for some reason doesn't vendorize the requisite specification file for that vendorized gem. You may have to run the following command in the respective gem's vendorized directory:

gem specification gem_name_without_version_number > .specification

Here is an example of my case wherein, I vendorized the factory girl post my installing it in my gemset and tried running the server. I got a warning message as below:

config.gem: Unpacked gem factory_girl-1.3.3 in vendor/gems has no specification file. Run 'rake gems:refresh_specs' to fix this.


kartz@desktop:~/MyRubyProjects/my_project$ cd vendor/gems/factory_girl-1.3.3/

kartz@desktop:~/MyRubyProjects/my_project/vendor/gems/factory_girl-1.3.3/$ gem specification factory_girl > .specification

After this I tried running the server or any rake task, and yeah as told earlier the warning message vanished....

Recommended reading:
Serious about learning and appreciating Ruby? Then, I strongly recommend reading
 

April 20, 2011

How to disable gnome-ssh-askpass?


Today we had setup Git repo with access to it through corporate's LDAP authentication. From the client machines we can access it using the .netrc (where the machine, login and password are configured).
However, for some wierd reason, upon trying to pull/push commits from/to the Git repository, the bash shell tries to open the gnome-ssh-askpass dialogue and it fails. I wanted to prevent the bash shell from attempting to launch the dialogue box. To do this, all I had to do is run the following command in the terminal:
$ unset SSH_ASKPASS

To prevent it in future, you can add the above line in your .bashrc or .bash_profile.

Wish you trouble-free working!

No DHCPOFFERS received. No working leases in persistent database - sleeping.


I was getting this weird error "No DHCPOFFERS received. No working leases in persistent database - sleeping.", when trying to connect to internet via WIFI in Ubuntu.
After enough googling to no avail, and by sheer serendipity I solved this. This worked for me; may be it helps you too.

Argh, I missed the point. So here is what you can try if you are stil having this issue.
Step 1: Go to, System -> Preferences -> Network Connections
Step 2: Select Wireless tab
Step 3: Click "Edit" the wifi connection profile you have created
Step 4: There are two connection modes - Ad hoc and Infrastructure. Choose the "Infrastructure" mode
Step 5: Save and try connecting again. You are done...!

April 3, 2011

GVim, Vim, Vi key-board short-cuts


  • Switch between tabs

    Ctrl+PageUp, Ctrl+PageDown
    Ctrl + Shift + UpArrowCtrl + Shift + DownArrow

  • Move to Nth tab in gvim
    gt, gT
    Note: The advantage with using gt, gT keys are that you can move to [N]th tab. For eg., if you want to go to 3rd tab type 3gt


  • Open a file in new tab from NERDTree while still remaining in NERDTree

    T will open the selected file in new tab, without changing focus from NERDTree
    t will open the selected file in new tab, and changes focus to that tab


  • Recursively Open all child nodes     

    Activate the NERDTree and navigate to the directory whose all child nodes must open.
    Now press O (capital) to expanded list of child nodes
  

  • Recursively Close all child nodes

    Activate the NERDTree and navigate to the directory whose all child nodes must close.
    Now press X (capital) to collapsed list of child nodes


  • Close all tabs at once with a single command, when I have multiple tabs open

    If no files are modified, then
    :qa
    To save work in all tabs and exit, then
    :wqa
    :xa
    To close all other tabs, except the active one:
    :tabo
    To close all tabs and open buffers
    :qall
    :tabdo :q   (The :tabdo will execute the command passed to it - in this case :q - for all the open tabs)

  • Text object selection

    Select text between Single Quotes
    When cursor is within the single quotes ('), type vi'

    Select text between Paranthesis block ()
    When cursor is within the Paranthesis block (), type vib

    Select text between Curly braces block ()
    When cursor is within the Curly braces block (), type viB

    Note: To make the selections "inclusive" of quotes, parenthesis or braces you can use a instead of i

    More on this can be read at Text object selection
  
  • Create a file or directory in NERDTree
     Activate the NERDTree and navigate to the directory in which the file/directory should be created.    Then press m to bring-up the NERDTree File-system Menu and choose a for "add child node". Now enter the file/directory name and you are done. Note that directory name should end with forward slash - /.

  • Rename a file or directory in NERDTree
    Activate the NERDTree and navigate to the directory in which the file/directory should be renamed. Then press m to bring-up the NERDTree File-system Menu and choose m for "move the current node". Moving is same as Renaming! Now enter the file/directory name and you are done. Note that directory name should end with forward slash - /.

  • Start VIM with NERDTree opened automatically
    Add the line below to your .vimrc:
    NERDTree

  • Auto-open NERDTree in every tab
    Add the two below lines to your ~/.vimrc:
    autocmd VimEnter * NERDTree
    autocmd BufEnter * NERDTree

March 31, 2011

Consolidating DB migration in Rails


In my current project we used to maintain a good number of rails migration scripts until, one guest developer stepped into the team for a short while and shared his knowledge on consolidating Rails DB migrations which I intend to blog about in this post.

So what is consolidating DB migrations all about? So if you have the DB migrations say, 1_aaa.rb, 2_bbb.rb and 3_ccc.rb that has gone into your production release 1.00, post your successful release (or a day or two after that), you can consolidate the scripts to something, say 3_consolidated_migrations.rb, wherein this new script essentially borrows the id (here it's 3) from the last run migration in production release and the contents being the same as schema.rb

So what are the implications of this? Well you need to keep in mind of the following:

  1. Without this approach being adopted, we can just about run the DB migrations on DB dump irrespective of its snapshot date. To put it other way, adopting this practice implies that you'll necessarily have to get the snapshot of Production DB that is no behind the release - say, if you have made released v3, then the DB snapshot has to be after release v3 is made successful. 
  2. If you had written data migration scripts, say from a table1.column1 to table2.column2, these would be lost. However, is there a point of having them in the scripts beyond successful release to production? In most of the occassions, your answer will be NO. However, if you have a compelling reason to have such data migration scripts in Rails DB migrations, then you may not choose DB consolidation.
  3. This one is very important to reckon with. If your DB migrations have scripts related to DB constraints - primary and foreign key, then all these will be lost with DB Consolidation, as we don't have rails api that is DB agnostic. As a work around you may maintain these scripts in separate DB specific .sql file - something like oracle_db_constraints.sql. In our project, whenever we had to introduce this kind of constraints, we had it both in DB migrations script specific for that release and add the same to the list of SQL(s) in the .sql file(s) that we maintain separately.
  4. Some Rails team adopt the practice of including scripts for seed data insertion, in the db  migrations scripts. This will be lost with DB consolidation, which in my opinion is a good one because it then forces the team to have a seperate file for this purpose (remember 'Seperation of Concerns' here). The other approach is to exclude this specific migration file from DB consolidation code based on this file pattern, which in my humble opinion is not bad thing.

March 30, 2011

tar command (with compress option)


Reading through the Unix's man or manual for a command description may be a little pain but with repeated practice you get used to it. In this blog I mix the manual's content and add my own example which might be of frequent use in general.

SYNOPSIS

tar [-] A --catenate --concatenate |
           c --create |
           d --diff --compare |
              --delete |
           r --append |
           t --list |
             --test-label |
           u --update |
           x --extract
              --get [options] [pathname ...]

DESCRIPTION

Tar stores and extracts files from a tape or disk archive. The first argument to tar should be a function; either one of the letters Acdrtux, or one of the long function names.

Some options take a parameter; with the single-letter form these must be given as separate arguments. With the long form, they may be given by appending = value to the option.

FUNCTION LETTERS

-A, --catenate, --concatenate
     append tar files to an archive
-c, --create
     create a new archive
-d, --diff, --compare
     find differences between archive and file system
--delete
     delete from the archive (not on mag tapes!)
-r, --append
     append files to the end of an archive
-t, --list
     list the contents of an archive
--test-label
     test the archive volume label and exit
-u, --update
     only append files newer than copy in archive
-x, --extract, --get
     extract files from an archive

OTHER OPTIONS

-a, --auto-compress
     use archive suffix to determine the compression program
--add-file=FILE
     add given FILE to the archive (useful if its name starts with a dash)
--atime-preserve
     preserve access times on dumped files, either by restoring the times
--no-auto-compress
     do not use archive suffix to determine the compression program
-C, --directory DIR
     change to directory DIR
--checkpoint
     display progress messages every NUMBERth record (default 10)
--exclude-vcs
     exclude version control system directories
-f, --file ARCHIVE
     use archive file or device ARCHIVE
--force-local
     archive file is local even if it has a colon
-h, --dereference
     follow symlinks; archive and dump the files they point to
--hard-dereference
     follow hard links; archive and dump the files they refer to
--ignore-case
     ignore case
--no-ignore-case
     case sensitive matching (default)
-k, --keep-old-files
     don't replace existing files when extracting
--keep-newer-files
     don't replace existing files that are newer than their archive copies
-X, --exclude-from FILE
     exclude patterns listed in FILE
-z, --gzip, --gunzip --ungzip
     filter the archive through gzip
-Z, --compress, --uncompress
     filter the archive through compress

EXAMPLES

Create .tar archive from files foo and bar
     $ tar -cf archive.tar foo bar
List all files in .tar archive verbosely
     $ tar -tvf archive.tar
Extract all files from .tar archive
     $ tar -xf archive.tar
Create zipped .tar archive from /home/karthik/myprojects
     $ tar -zcvf myprojects.tar.gz /home/karthik/myprojects
Unzip and Restore an archive myprojects.tar.gz to say current directory
     $ tar -zxvf myprojects.tar.gz
Unzip and Restore an archive myprojects.tar.gz to an existing directory say /temp
     $ tar -zxvf myprojects.tar.gz /temp

February 9, 2011

No more cron jobs. Schedule jobs through rufus-scheduler in rails.

In the project that I'm working currently, I was asked to look out for ways to replace the scheduling jobs through crontab in favour of some scheduler that can control/schedule run the tasks at regular interval as long as the application is up and running. Thanks to my comrade in Dev-Ops team (Ranjib Dey) who  directing my attention to rufus-scheduler.

rufus-scheduler - Things can't be simpler! Let us see how simple it is in action with a sample code 

First step to usage is install the gem; so, find below the command for the same. You run it from the root of your application folder and I assume that you use rvm (if not, prefix the command with - sudo )

> gem install rufus-scheduler

Now, when the rails application gets kick-started, it reads all .rb files under config/initializers directory as part of its initialization process. This step in rails start-up, is what we'll take advantage of. So, let us create a new file, say my_tasks_scheduler.rb, in config/initializers directory.

<my_rails_app>

   | -- app

   | -- config

          | -- initializers

                    | -- my_tasks_scheduler.rb

   | -- db

   | -- ...

   | -- ...

   | -- lib

          | -- tasks

                    | -- tempfile.rake

The contents of the file my_tasks_scheduler.rb would be like:


require 'rufus/scheduler'  # Need this to make use of Rufus::Scheduler

require 'rubygems'   # Need this to make use of any Gem, in our case it is rufus-scheduler

require 'rake'     # Need this to make use of Rake::Task

#  'tempfile.rake' is the rake file I had defined under lib/tasks directory in my rails application

load File.join(RAILS_ROOT'lib''tasks''tempfile.rake')
# 'misc.rake' is the rake file defined under railties/lib/tasks directory of the installed rails version that your application makes use of.     

# 'misc.rake' is not required to be loaded if none of your rake tasks that you invoke are dependent on :environment task, directly or indirectly
# If this file is not loaded, you would see an error message like "Don't know how to build task :environment"
load File.join('lib', 'tasks', 'misc.rake')  

# OPTION 1: If you want to run the scheduler as part of your very own rails process then you may adopt this option

temp_files_cleaning_scheduler = Rufus::Scheduler.start_new
# Making use of the syntax used in Crontab

temp_files_cleaning_scheduler.cron '*/1 * * * *' do  

  task = Rake::Task["tempfile:delete_all"

  task.reenable  # If only you do this, will your rake task run the next time you invoke it.

  task.invoke
end


#OPTION 2: If for whatever reason (say, for performance reasons) you want to run your rake tasks as seperate process independent of your rails application, then you may adopt this option


temp_files_cleaning_scheduler = Rufus::Scheduler.start_new  
#Making use of a more intutive approach, instead of Cron syntax

temp_files_cleaning_scheduler.every "1m" do  
    # Programmatically, kick-starting the rake task from the command line

   system "rake tempfile:delete_all RAILS_ENV=#{RAILS.env}"  

end


And that is it, you are all set for action... 


Additional references that are worth reading are mentioned below:



February 1, 2011

Externalizing ALL application specific configurations to a file outside of Rails ROOT

It has been quite a while since I wanted to externalize all application specific configurations to a file outside of Rails ROOT, so that when my application is deployed in production, it picks up the configurations from a file in some specific location outside of Rails environment. The sysadmin makes changes to this file as is required and he alone knows or is eligible to know all these configuration details and certainly not the development team.

The application that I'm having in my mind is an internal rails application that gets deployed in an internal hosting environment instead of hosting it in a external environment like Heroku, etc.

Follow through the self-explanatory code snippets to get an understanding of how I achieve it in simple way. For the noobs, the quick explanation would be that the code snippet in environment.rb file reads the YAML file from system to copy all key value pairs to Rails' ENV hash. This ENV hash is available everywhere while/on/after application load.  

File: config/environment.rb
# Mechanism to load all application related configurations
$CONFIG_FILE = "/var/myapp/config/jsconfig.yml"
require 'yaml'
APP_CONFIG = YAML.load_file($CONFIG_FILE)
APP_CONFIG.each do |key, value|
  ENV[key] = value
end

#3rd Party Server's (that my application is using) Configurations here...
3RD_PARTY_SERVER_URL = ENV['3rd_party_webservice_endpoint_url']
3RD_PARTY_SERVER_CREDENTIALS = {:username => ENV['3rd_party_server_username'], :password=> ENV['3rd_party_server_password']}


File: /var/myapp/config/jsconfig.yml
3rd_party_webservice_endpoint_url: url
3rd_party_server_username: username
3rd_party_server_password: password
myapp_db_url: jdbc:oracle:thin:@localhost:1521:XE
myapp_db_username: kartz
myapp_db_password: rails_savvy


File: /var/myapp/config/database.yml
development:
  adapter: oracle_enhanced
  url: <%= ENV['myapp_db_url'] %>
  username: <%= ENV['myapp_db_username'] %>
  password: <%= ENV['myapp_db_password'] %>
  encoding: utf8

test:
  adapter: oracle_enhanced
  url: <%= ENV['myapp_db_url'] %>
  username: <%= ENV['myapp_db_username'] %>
  password: <%= ENV['myapp_db_password'] %>
  encoding: utf8

production:
  adapter: oracle_enhanced
  url: <%= ENV['myapp_db_url'] %>
  username: <%= ENV['myapp_db_username'] %>
  password: <%= ENV['myapp_db_password'] %>
  encoding: utf8



I'm a wannabe reader for the book,

January 25, 2011

Run SQL in Unix Shell

While reading the book - Agile Web Development with Rails, Third Edition - I have come across a section where the authors show how to run a SQL against a sqlite3 database. Want to know where in that book you can find it? Go purchase the book and find it yourself :P

Now back to my business of curiosity - I wanted to know how do I do this in every other databases that I have used so for. This blog post is a record of that endeavor. This should be very handy mainly for the Rails developers.

Unix, SQL and SQlite3

linux_prompt$ sqlite3 db_file_name.sqlite3 "SELECT * FROM my_db_table"

linux_prompt$ sqlite3 db/development.sqlite3 "SELECT count(*) from schema_migrations"

linux_prompt$ sqlite3 db/development.sqlite3 <<EOF
> SELECT * FROM users; --where 'users' is a table in my development.sqlite3 DB 
> SELECT * FROM schema_migrations; --where 'schema_migrations' is a table in my development.sqlite3 DB
>EOF


Unix, SQL and MySQL

linux_prompt$ export username="dbuser"
linux_prompt$ export password="dbpassword"
linux_prompt$ export db="mydatabase"

linux_prompt$ mysql -u "$username" -p "$password" "$db" <<EOF
> SELECT * FROM users; --where 'users' is a table in my development.sqlite3 DB 
> SELECT * FROM schema_migrations; --where 'schema_migrations' is a table in my development.sqlite3 DB
>EOF

linux_prompt$ mysql -u "$username" -p "$password" <<EOF
> use $db
> SELECT * FROM users; --where 'users' is a table in my development.sqlite3 DB 
> SELECT * FROM schema_migrations; --where 'schema_migrations' is a table in my development.sqlite3 DB
>EOF


Unix, SQL and Oracle

linux_prompt$ export username="dbuser"
linux_prompt$ export password="dbpassword"
linux_prompt$ export db="mydatabase"

linux_prompt$ sqlplus -S $username/$password <<EOF
> SELECT * FROM users; --where 'users' is a table in my development.sqlite3 DB 
> SELECT * FROM schema_migrations; --where 'schema_migrations' is a table in my development.sqlite3 DB
> exit; --command to exit sqlplus environment
>EOF

linux_prompt$ sqlplus -S $username/$password @sql_script_file.sql