Sunday, 29 April 2012

Exception Handling in Ruby part 2(Raising an Exception / User defined Exception)

Sometimes the neither the system nor the language detect an error, but you do. Perhaps the user input someone 18 years old for Medicare. Linux doesn't know that's wrong. Ruby doesn't know that's wrong. But you do.

You can raise a generic exception (or the current exception if there is one) like this:
raise if age < 65

 age = 60
 puts 'Here 1'
 raise "Text" unless age < 65
 puts 'Here 2'
rescue MyError
 puts 'Here 3 - MyError encountered'
 retry   // here if you want to run that code which is produced error use retry
rescue StandardError
 puts "Here 4 - Other error encountered (#{$!.inspect})" + caller.inspect
 puts 'Here 5 - No errors'
 puts 'Here 6 - Always done'

Exceptions are handled by blocks. The risky code goes into the first chunk of the block. If an exception is encountered, the program will jump to the end of that chunk and look for an appropriate action. In the above example, it will first look at rescue MyError. If the exception is of the MyError class - or a sub-class - then the program will not run the code folling the rescue. Note that you can list multiple exception classes, separated by commas.

Otherwise, it will look further. The next rescue is for StandardError, so this will catch all errors of the StandardError type or its sub-classes - except for MyClass, as that would have been caught earlier. All rescuable exceptions must inherit from StandardError (but see later), so this is set up to catch all exceptions, but that need not be the case; uncaught exceptions will be passed on up the stack to whatever else might handle them.

The else chunk will get performed after the initial chunk has completed successfully (i.e., without raising an exception). Finally, the ensurechunk gets performed whatever the outcome.

An exception is raised using the raise keyword. Exceptions are just objects, so are instantiated just like any other object. They typically take a string parameter, which you can use to give a descriptive message. Alternatively, you use this form:
raise "Test"
raise MyError, "Text", caller
raise MyError, "Text"
raise "Text"     # For the default RuntimeError

You can put a retry in a rescue chunk, as in the example above. The program will jump back to the start of the block, and start again. In the second rescue chunk, there is a raise on its own. This will pass the exception ouside of the block, to be handled by some higher up error handling system.

Also in that chunk, note that the $! code is the exception. If you prefer, you can set your own name for this.
rescue StandardError => err
 puts "Here 4 - Other error encountered (#{err.inspect})" + caller.inspect
Here is the output from the first example:
Here 1
Here 3 - MyError encountered
Here 1
Here 3 - MyError encountered
Here 1
Here 3 - MyError encountered
Here 1
Here 3 - MyError encountered
Here 1
Here 3 - MyError encountered
Here 1
Here 2
Here 5 - No errors
Here 6 - Always done

Stack Trace
To see the stack trace, use the backtrace method. This returns an array of strings. To just see the top dozen entries, you could use this:
$!.backtrace[0..12] * "\n"

Exceptions that do not inherit from StandardError
The superclass for all exceptions is Exception. The theory is that all exceptions that a program should be expected to recover from are either StandardError or a subclass of it, which is why I described them as "rescuable exceptions " earlier. If no exception is specified, rescue will default to StandardError.

However, there may be times you want to recover from other exceptions. A particular example I came across is a SyntaxError thrown by ERB. The offending syntax was in a data file, not my application; my application should have caught the error, and reported it back to the user. This is entirely different to a syntax error in my code, and in my opinion ERB should throw its own exceptions that inherit fromStandardError. Time-out errors are another example, as discussed here.

To catch all exceptions use:
rescue Exception

The rescue statement modifier
Rescue can be used in a way analogous to if and unless. For example:
test rescue do_stuff

This statement will run the method test, and if it encounters an error (specifically StandardError or subclasses) it will invoke do_stuff. You can use this to assign a default value if a method fails, like this:
s = test rescue "Default value"

The rescue stament returns the value "Default Value". You could write it with brackets, which might help make sense of it:
s = (test rescue "Default value")

You can concatenate statement with semi-colons, but cannot use blocks.
s = test rescue do_stuff; "Default value"

Catch and Throw
The catch and throw facility in Ruby is not really exception handling at all, though it does have similarities. As it shares keywords with Java exception handling, it seems to get lumped into any discussion on exceptions. This page is no different.

Calling a throw will interrupt the program flow, causing it to jump to the named catch. Use this format to set up a catch block. Any timethrow :my_label is called within the block (including within methods called from the block).
catch :my_label do
throw :my_label
 do_not_do this_stuff

You can use the throw to return a value to catch (which will be nil otherwise).
value = catch :my_label do
throw :my_label, "My result"
 do_not_do this_stuff

Exception Handling in ruby part 1(Exception Hierarchy of ruby)

 Exception Hierarchy

An exception is a special kind of object, an instance of the class Exception or a descendant of that class that represents some kind of exceptional condition; it indicates that something has gone wrong. When this occurs, an exception is raised (or thrown). By default, Ruby programs terminate when an exception occurs. But it is possible to declare exception handlers. An exception handler is a block of code that is executed if an exception occurs during the execution of some other block of code. Raising an exception means stopping normal execution of the program and transferring the flow-of-control to the exception handling code where you either deal with the problem that's been encountered or exit the program completely. Which of these happens - dealing with it or aborting the program - depends on whether you have provided a rescue clause (rescue is a fundamental part of the Ruby language). If you haven't provided such a clause, the program terminates; if you have, control flows to the rescue clause.
Ruby has some predefined classes - Exception and its children - that help you to handle errors that can occur in your program. The following figure shows the Ruby exception hierarchy.

  1. Fatal(fatal)
  2. NoMemoryError
  3. ScriptError
    • LoadError
    • NotImplementedError
    • SyntaxError
  4. SignalException
    • Interrupt
  5. StandardError
    1. ArgumentError
    2. IOError
      • EOFError
    3. IndexError
    4. LocalJumpError
    5. NameError
      • NoMethodError
    6. RangeError
      • FloatDomainError
    7. RegexpError
    8. RuntimeError
    9. SecurityError
    10. SystemCallError
      • Errorno::__ (ENOENT, etc.) (system-dependent)
    11. ThreadError
    12. TypeError
    13. ZeroDivisionError
  6. SystemExit
  7. SystemStackError

Monday, 2 April 2012

Planning to buy new notebook - don't want windows os

I was planning to buy a new notebook as the old one is taking its last breath. But I dont want to pay 3.5 - 4K extra for Windows. Being a true Indian, I believe in pirated version of software/os and if Ubuntu is there, who the hell care for "genuine" Windows. So while searching for a non-windows notebook, I came across this post. Hope you will find it helpful. 

Windows tax refund for Acer notebook (Acer Aspire 1410/1810T) 

If you have never heard about Windows tax, Windows refund or anyone ever getting refund for Windows OS then perhaps it is time to look it up.

I don't think many people are aware of the fact that it is possible (and you have the right to) to get a refund for Windows OS if you are not planning to use it.

Getting Windows OS refund is like returning unused/unneeded product to get your money back. For example, if you are using Linux on your computer, why should you pay for Windows OS? Or, if your study institution provides FREE premium Windows OS (which is the case for Computer Science students), why should you pay for the crippled version that comes pre-installed on your computer?

Please note: The key in getting Windows OS refund is in DECLINING the EULA agreementthe first time computer boots up (or not turning computer on at all). If you accepted the EULA you may be out of luck! Even if the EULA was accepted (such is the case with Open-box or pre-setup computers), you can still get a refund as long as you do a system restore to return the computer to the factory state.

It is best to get the refund in first few weeks after you bought your computer. You can use Linux live CDs to test your system to make sure it works properly, or you can boot from your own HDD (with Linux or Windows) and check to make sure everything works. Once you make up your decision for keeping the computer, give manufacturer a call and ask for a Windows refund.

Here is how I got Windows OS refund from Acer Canada:
I purchased my Acer Aspire 1410 from Canadian Staples Business Depot. For 5 days I tested it by booting Ubuntu Linux from SDHC card to make sure the computer was working correctly. After making the final decision of keeping this notebook, I picked up the phone and called Acer Technical Support (1-866-706-2237).

After getting a hold of an agent, I explained that I would like to get a refund for Windows Vista Home Premium that came pre-installed on my laptop, and quoted the terms of the EULA agreement:
By using the software, you accept these terms [of EULA agreement]. If you do not accept them, do not use the software. Instead, contact the manufacturer or installer to determine their return policy for a refund or credit.
He kept telling me that Acer does not have any Windows OS refund policies of any kind, and in fact, there is no way to remove Windows OS from the computer  . I asked to speak to his supervisor ("Level 2 agent"). He said that I need to register my laptop before I can get Level 2 support.

Upon completion of registration, he forwarded my call to a Level 2 agent. After repeating (for 11th time?) that I would like to get a refund for an unused Windows OS, she said that there INDEED IS SUCH A POLICY! She said that I will need to send my laptop to Acer Repair Depot so that they can (1) delete all traces of Windows OS, (2) remove OEM sticker on the bottom and (3) delete Windows OS activation settings from BIOS (I guess she had SLIC in mind? Doesn't simple BIOS flash restore it back?  ). I asked how much money I will receive as refund and she responded that for Windows Vista Basic they give$65CAD, but was unsure about Home Premium. I asked her to sign me up for a refund.

Apparently, since my laptop was within 30days from purchase date, I was eligible for FREE shipping to Repair Depot (Acer's policy). After confirming some shipping details, she forwarded a Purolator prepaid shipping label and service request number along with instructions to my email. I thanked her and ended the call.

I securely packed my laptop (just the laptop, without battery or any other accessories) and as per Acer's email instructions wrote my name, phone, Service request and S/N numbers on the box. Printed off and attached the shipping label. The box was picked up by Purolator the next day.

On the 8th day after sending my laptop to Acer, I received email notification that I should be getting my laptop back shortly and included FedEx tracking number.

The box from Acer was delivered to my doorstep by FedEx the next day. I was very surprised to find that the laptop (wiped HDD, OEM sticker removed) was the only thing in the box. Where the hell was my Windows OS refund check? 

A quick call to Acer revealed that I should be getting my check within 6 weeks in regular mail. Hooray!! 

6 weeks after my first phone call I still haven't received my refund check. I called Acer support and inquired about my refund check. They said that the order for the check has not been placed with their financial department and after I complained they filled out an order for a refund.
8 weeks after my first phone call to Acer, I have received the Windows tax refund check for $60.48USD, which was equivalent to $65CAD at the time. Here is a scanned copy:

It took me 45mins of telephone calls, 9 days without laptop and 7 weeks wait to get Windows Vista Home Premium refund of $65CAD. Was it worth it? You bet 

Acer Aspire TimelineX 3820TG Windows tax refund
Update (24/12/2010): Just bought an Acer Aspire 3820TG-3022 with Windows 7 Home Premium from Staples. Apparently, it was pre-setup ("plug and play PC") by in-store technicians for "best customer experience". They have kindly accepted the EULA license agreement for me and installed more crapware. Now that agreement has been accepted, I wonder if I can wipe out the drive and return the OS...

Update (14/01/2011): Wiped HDD and restored from recovery DVDs burned by Staples. Called Acer and within 5minutes (I am not kidding, it was that fast) I had all the instructions in my email box. They refused to pay for shipping, because Windows is not a "manufacturing defect" (I could argue with that  ) therefore I am not eligible for their 30day free repair depot shipping.

Update (16/01/2011): Sent my laptop to Acer via FedEx. Should be there on 19/01/2011. FedEx wanted me to pay $80 for air shipping, but I refused and paid ground $12 + insurance $12. Apparently, it will arrive there just as fast as if I sent it by air. Probably by the same delivery truck too.

Update (24/01/2011): I received my laptop a week after sending it. Windows was gone. Wow, I am impressed by Acer support! Will be calling Acer in a month to remind about the refund check.
I am really impressed at how fast the process went this time. Only 5 minutes on the phone and 1 week turnaround. Awesome.

Update (31/03/2011): I knew I shouldn't have trusted Acer with sending me a refund check. I called them today, and I was told that they are unaware of any refund checks that were supposed to be sent to me. I asked them to open a case number and file it with their financial department. That is what the agent did. In addition, I have asked how they usually know when to send someone an OS refund check. Apparently, they don't. You have to call them and tell them your OS was removed and you need a refund check. If you don't do that, then you will never get your refund.

Tips and Tricks
0. Please NOTE: The Acer policies differ from country to country. For example, in the UK itmay not be worthwhile to ask for Windows refund.
1. If you are planning to get Windows OS refund DO NOT accept EULA.
2. Caller Acer USA/Canada support about 3PM EST (8PM GMT) on a business day to minimize wait time and to be sure you can get to the Level 2 agent without hassle.
3. General agents are unaware of all the Acer's policies (especially about Windows OS refund policy) so do not waste your time convincing them such policy exists. They may spend a great deal of energy on convincing you to give up, but DO NOT LISTEN -- IT IS ALL LIES  ! Simply explain what you want, and ask to be forwarded to Level 2 support.
4. The general agent CANNOT authorise Windows OS refund. YOU MUST talk to Level 2 support for it. So you can avoid wasting time -- just register and ask to be forwarded to Level 2 agent.
5. If they keep refusing to admit there is a Windows OS refund policy then simply hang up and call back or ask to be forwarded to a different agent.
6. If you are within 30days from purchase date then ask for "free shipping to repair deport if within 30days" policy. You should be able to get your prepaid label.
7. Search on the Internet for Windows OS refund cases to gather up some info.
8. If all else fails you can still sue Acer  It has been done before

Monday, 26 March 2012

bullet 2.3.0 released

bullet is a gem to help you increase your application's performance by reducing the number of sql requests it makes. Today I released bullet 2.3.0 to better support rails 3.1 and 3.2 and performance improved. It's a long time I didn't do any changes to bullet, let me tell you the story I work for bullet 2.3.0.
bullet is a gem to help we enlarge your application’s opening by shortening a series of sql requests it makes. bullet 2.3.0 got 10% opening softened for activerecord 3.0.12, it functions most quicker, bullet for ar 3.1.4 is 48% quicker than for ar 3.0.12, as well as for ar 3.2.2 is 40% quicker than for ar 3.0.12
At the beginning of this month, bullet got its 1000th watcher on github, I realized it's time to improve it e.g. speed up and compatible with edge rails.
The first thing I did is to refactor tests. Before I created several rspec tests, but they are more like integration tests instead of unit tests, so I move them to spec/integration/ directory. Then I added a bunch of test units to cover all codes, which can promise the correctness of further code refactors. I also use guard instead of watchr to do auto tests, why I preferred guard? It's much easier and has more extensions, like guard-rspec.
Then I moved AR models, which are used for integration tests, from integration tests to spec/models, and I also moved db connection, db schema and db seed to spec/support/, moved test helpers to spec/support/ as well. Now my tests looks much cleaner and run much faster (only connect db once).
After refactoring tests, I tried to improve the bullet performance, I already created a benchmark scriptbefore, bullet 2.2.1 with rails 3.0.12 spent 30s to complete
bullet 2.2.1 with rails 3.0.12
                                                                             user     system      total        real
Querying & Iterating 1000 Posts with 10000 Comments and 100 Users       29.970000   0.270000  30.240000 ( 30.452083)
Then I used perftools.rb to measure cpu time for methods, the result is garbage_collector, String#=~ and Kernel#caller
  1. garbage_collector, it depends on how many objects allocated
  2. String#=~, bullet use regexp to check if caller contains load_target
  3. Kernel#caller, bullet uses caller to tell what codes caused n+1 query
I found the easiest is to mitigate String#=~, as bullet only check regexp with constant string load_target, so I simply used .include?("load_target") instead.
bullet 2.3.0 with rails 3.0.12
                                                                             user     system      total        real
Querying & Iterating 1000 Posts with 10000 Comments and 100 Users       26.120000   0.430000  26.550000 ( 27.179304)
another change is to store object's ar_key instead of object itself.
{<#Post id:1, title:"post1", body:"post body", created_at:..., updated_at:...> => [:comments]}
{"Post:1" => [:comments]}
it speeds up hash comparison time and save the hash size.
I also hacked ActiveRecord::Associations::SingularAssociation#reader instead of ActiveRecord::Associations::Association#load_target for rails 3.1 and 3.2, it fixes activerecord 3.1 and 3.2 compatibility, there is no need to call caller in Association#load_target, it runs much faster in rails 3.1 and 3.2, the following is the benchmark result
bullet 2.3.0 with rails 3.2.2
                                                                             user     system      total        real
Querying & Iterating 1000 Posts with 10000 Comments and 100 Users       16.460000   0.190000  16.650000 ( 16.968246)

bullet 2.3.0 with rails 3.1.4
                                                                             user     system      total        real
Querying & Iterating 1000 Posts with 10000 Comments and 100 Users       14.600000   0.130000  14.730000 ( 14.937590)
Enjoy the new bullet gem!