Wednesday, November 19, 2008

A perfetc world.. A world without IE ??

It becomes a huge list when you pen down the IE bugs(even features), some of which you can't even dream of.
I had my share of problems struggling for hours to get things work on a buggy IE(I refer to IE6 & IE7 which makes no difference).

As I feel it probably a fitting context, I can't stop quoting this by someone on Ajaxian.
"
If you've been working with the Ajax framework long enough, I'm sure you've run into at least a few speed bumps thanks to Internet Explorer. Not a day goes by that I don't have to rewrite a line of code, or tweak my css in order for IE to render what I think it should. But alas, this is the nature of software that comes from a company that views Standard Compliances as recommendations."

Let me share with you a couple of issues I had to face.

Recently, in my web-page, it was needed to dynamically change the options of a SELECT box. What I was doing was construct a string with options and append the the options string to the SELECT tag using innerHTML. This worked perfectly on my favourite FF and even on Safari. I am pretty sure it would have worked on any browser, you name it, with the exception of IE.

Here is my code:
var optionString = "";
for(option in options) {
optionString += ''+data[option]+'';
}
var sel = Document.getElementById("mySelectBoxId");
sel.innerHTML = optionString;
What's happening in IE was, the first option tag is getting truncated and my SELECT box is shown empty.
I broke my head examining my code for a bug but found none. The mighty Google to the rescue. It was revealed that this was because of this BUG in IE.
IE recommends using DOM to achieve this and which I did to effect.

The other issue is while using AJAX. I don't call it a bug(its rather more of a feature). I have a list of items which can be re-ordered by drag-drop. Whenever an item gets dragged, I make an AJAX GEt request to the server and a re-ordered list of items had to served as response. Again this works fine with FF and Safari. The problem is with IE again.

When one of the item is dragged, IE is not always making a request to the server but the list gets re-ordered wrongly on the browser. It took me a whole day to figure out where things were going wrong.

IE is not making the request but serving a stale cached response from previous requests which are identical. Some argue that its a feature with any browser to cache a response from a GET request. But IE's caching has always been an issue.

We have two solutions for the above problem.
One by making a POST request instead of a GET so that IE won't cache it.
"But I can't convince myself to make a POST request just to satisify IE where a simple GET best fits the job. "
The other is to make your every request unique. For this you can append a random string or a timestamp as a useless parameter at the end of your request URL.
"By making requests unique, you can achieve a proper response from the server in this case, but IE still caches this response. When these requests are numerous, the browser cache overflows and you may loose some important cached response of other requests."

So, there is always a trade off involved. Its upto the developer to choose a solution that best fits his job.

The list doesn't end here. It's just that I didn't come across but others might have. I will keep adding such issues if any. I wish I don't.

"
Have fun with you code and don't hate it :) hate the things that don't comply to the standards..."
Now is it a fitting description to call it A perfect world.. A world without IE ??

Sunday, September 28, 2008

auto complete issue with non-Mozilla browsers

Hi,
Playing with auto complete in Firefox is fun all the time , but this is not going to be same in Others Browsers(IE & Safari),
after Googling for many days i came up with a pleasant solution.

Rails2.0: auto_complete is now a plugin (it’s not in the core anymore), you will install it before using it:
script/plugin install auto_complete

Somewhere in your views you’ll want code somewhat like the following.
<%= text_field_with_auto_complete :article, :contains, { :size => 15 }, :skip_style => true %>

I specified a size for the text area with the :size => 15 values in the hash. I also included :skip_style => true which keeps the helper from automatically inlining CSS styles into the page.

and now the major issue i faced with IE and Safari browsers are :
Q. Up, Down arrow keys are not working for auto complete in non-mozilla browsers when drop down list appears
The solution is ..
This is due to a bug in Scriptaculous. At the time of writing you will need to apply the following patch that will fix it:
in controls.js around line 86 you will observe these lines
Element.hide(this.update);
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},

and now you modify above lines with the following code of lines :

Element.hide(this.update);
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));
// Observe keydown for non-Mozilla browsers per http://dev.rubyonrails.org/ticket/10126
if (Prototype.Browser.Gecko) {
Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));
} else {
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
}
},
and restart the server ,now the arrow keys will work in both IE and Safari browsers.

Wednesday, September 24, 2008

improving performance with :select in rails

For newbies, rails is amazing. With its constituent modules such as active-record, action-pack, action-mailer etc.. acting behind the scenes, rails provides a lot of abstraction to the developers making things more simpler. Given this simplicity through abstraction, there follow some issues which may degrade your application performance when not taken care of properly.

Let's have a look at Active Record. It is Active Record that makes people go crazy about rails. It shoulders the responsibility of database operations for the users providing them with different flavours of methods to deal with. But there are some pitfalls to consider:

1. The default 'find' method fetches all columns from a table row:
Active Record works at the row level but not at the column level. Consider a table "employees" having emp_id, emp_name, emp_slary, emp_address and etc.. upto 50 columns. When you want to make a detailed list of all the employess, you may tend to write

@employees = Employee.find(:all).

The above statement fetches all the fifty columns of every single employee from the table and converts it as Employee objects. What if you need only a set of
columns(say
emp_id, emp_name, emp_slary, emp_address) but not all. Now you can achieve this using :select option in the find method
@employees = Employee.find(:all, :select => ['
emp_id', 'emp_name', 'emp_slary',
'emp_address
'])
What this does is select only the specified columns from the table and converts it into Employee objects. Accessing unspecified attributes from the resultant Employee objects may reult in an Error/Exception, but saves a lot of overhead in selecting all the columns and turning the rows into heavy objects.

Another case may be an articles table. Though it may seem to contain less number of columns, one tends to use a column for article body which may contain text as well as images(usually these type of columns are set to BLOB type). Here also, to make a list of all the articles, you can write


@articles = Article.find(:all, :select => ['article_id', 'article_title', 'author_name',
'published_date'
])

and avoid the body column if you feel not needed.You are free to use all the other options along with :select.

2. Eagerloaded associations that contain heavy data:

class Author < ActiveRecord::Base
has_many :articles
end

class Article < ActiveRecord::Base
belongs_to :author
has_many :comments
end

class Comment < ActiveRecord::Base
belongs_to :article
end

Assuming that you know how to eagerload associated models using :include option , lets look at how we can finegrain the eagerloaded models using the :select option with :include.

@author = Author.find(:id, :include => [:articles])

This fetches an author's record and all the article records that belong to this author. But how to avoid fetching the heavy 'body' column from articles table. Can we use the :select to fetch only the desired columns from the associated model through :include ? This is not possible because eagerloading generates SELECT statement too, the use of :select together with :include is not supported . This can be achieved with a bit of extra code:

Download the patch from http://dev.rubyonrails.org/attachment/ticket/7147/init.5.rb submitted by mrj to Rails Trac.
Place this file in your lib directory and require it in environment.rb. For ex, if the file is named 'include_with_select.rb' in your lib, you can write in your environment.rb as:
require 'include_with_select'.

With this setup, you can freely select the desired columns in the :included associations as:
@author = Author.find(:id, :include => [:articles[:article_id, :article_title, :author_name, :published_date]])

If you want to eagerload a set of comment attributes for every article, you can write it as:
@author = Author.find(:id, :include => [{:articles[:article_id, :article_title, :author_name, :published_date] => :comments[:comment_text, :comment_by]}])

This way we can achieve a better performance using :select with/without :include.

Thursday, September 18, 2008

have you ever measured your rails application performance?

Well, you have been developing rails applications for over a year or couple. You did every bit of it The Rails Way keeping it DRY, writing migrations, associating your models and built-in test cases. The app seems to work great on your local machine. But are you sure it does on the production server? Have you ever used any profiling or benchmarking tools to measure the performance of the apps? If not its time to use one and make sure your apps run faster not only during development but also in the production environment.

As there are many such tools that serve the purpose, the two head-to-head competitors, RPM from new relic and Five Runs from fiveruns , which are strongly backing the Rails framework to become enterprise ready, make a good choice.

Given the task to finetune a rails app, I preferred relic over fiveruns as it is very easy to get going. RPM Lite, a standard version of RPM is free as long as you want and you can always upgrade it to enjoy more featues. For a developer use, RPM Lite is enough.

RPM Lite is available as a plugin. I got the plug-in installation link through subscription at new relic, installed it and restarted my server.
Note: The plug-in installation creates a
config/newrelic.yml file. I didn't pay much attention to it. But it may contain some interesting configuration.


Now, whenever I made a request to the server, the relic plugin monitored my request and measured the time for processing my request. This is available at http://localhost:3000/newrelic.

Amazingly, relic tracked my request right from the controller to the model to the view.
1. It gave me an analysis of time spent in the controller, the model/db calls executed and to
render the results to my view to an accuracy of milli seconds.
2. It also produced a pie-chart of the processes involved.
3. It provided me with an sql view, where I could track the sql executed.
4. Number of such requests that could be server per second.
5. It also tracked AJAX requests.

From the analysis, I learnt that the app is spending most of the timein DB calls which I eventually reduced.
This way, I could make a better use of RPM and finetuned the app resulting in a notable performance boost. So, why not give it a try right now. I hope RPM will serve the purpose for you too.



Thursday, September 13, 2007

integrating google maps with rails applications

I have spent some time on integrating google maps with rails applications. I would like to share my work with you here.

I tried to post the code here but the blog site seems to be not supporting html tags. If anyone wants to have a look at the code, please feel free to email me at "ravivardhan.k@rknowsys.com"

thanks,
Ravi K .

Friday, August 31, 2007

Installing Aptana+RadRails plugin on ubuntu

I have taken all the pain installing Aptana 0.2.9(with radrails) on my ubuntu 7.04 machine and would like to present a better way of Aptana installation.

Following are the steps to be followed to get Aptana installed (with rails support) on ubuntu.

All the downloads are pointed to foo's desktop which is equivalent to the directory /home/foo/Desktop (foo is the user-name of
the current user of the system)

1. Download Aptana for linux from "http://www.web20.com/downloads/current/Linux/VM/Aptana_IDE_Setup.bin" to yuor Desktop.

2. After the download gets finished, open a terminal. Open /etc/apt/sources.list and make sure you have the universe
repository enabled:

sudo gedit /etc/apt/sources.list

deb http://de.archive.ubuntu.com/ubuntu/ edgy universe

3. If you had to modify /etc/apt/sources.list, you must update the package database afterwards:

sudo apt-het update

4. Aptana depends upon the following two packages. So, You need to install these as

sudo apt-get install mozilla libswt3.1-gtk-java

this will throw some error messages but dont take a note of that.Those errors rise because of the newer versions of those libraries
that already exist on the machine.

5. Now start the installation as

/bin/bash Aptana_IDE_Setup.bin wil throw some errors as

falko@falko-desktop:~/Desktop$ /bin/bash Aptana_IDE_Setup.bin

Preparing to install...
Extracting the JRE from the installer archive...
Unpacking the JRE...
Extracting the installation resources from the installer archive...
Configuring the installer for this system's environment...
nawk: error while loading shared libraries: libdl.so.2: cannot open shared object file: No such file or directory
dirname: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
/bin/ls: error while loading shared libraries: librt.so.1: cannot open shared object file: No such file or directory
basename: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
dirname: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
basename: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
hostname: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

Launching installer...

grep: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
/tmp/install.dir.7470/Linux/resource/jre/bin/java: error while loading shared libraries: libpthread.so.0: cannot open
shared object file: No such file or directory

If you get these error messages, do the following...

cp Aptana_IDE_Setup.bin Aptana_IDE_Setup.bin.bak
cat Aptana_IDE_Setup.bin.bak | \
sed "s/export LD_ASSUME_KERNEL/#xport LD_ASSUME_KERNEL/" > \
Aptana_IDE_Setup.bin

6. Aptana Installer will come up. Now accept the defaults and click on "Done" to finish the installation.

7. Create a script to set an environment variable (MOZILLA_FIVE_HOME) for Aptana and place it in /usr/bin

for that do the following: gedit aptana

this opens an empty text file named aptana in the gedit editor. Now place the following script in the opened file .

#/usr/bin
export MOZILLA_FIVE_HOME=/usr/lib/mozilla
~/Aptana/aptana

8. Now letrs make the file executable and place it in /uer/bin directory.For that

chmod 755 aptana
sudo mv aptana /usr/bin/

Aptana is now installed.


To create a menu entry for Aptana, just follow me :

9. Download the aptana icons from "http://www.aptana.com/trac/attachment/ticket/702/icons.zip" .

10. Extract the icons to yuor desktop.Move these icons to /usr/share/pixmaps/

sudo mv aptana_* /usr/share/pixmaps/

11. Right-click on Applications and select Edit Menus:

In the programming subcategory, click on "New Item".

In the Menu Item Properties window that pops up, fill in the following details:

Name : Aptana
Comment : Aptana
Command : aptana or /usr/bin/aptana (this is the script you have written earlier)

Now click on "No Icon" button.
In the file browser, navigate to /usr/share/pixmaps and select the aptana_32x32.png icon. Click on OK:
You will now see the Aptana icon in the Menu Item Properties window. Click on OK:
Then close the Menu Layout window:

12. Go to Applications -> Programming , you will find Aptana . Click on the Aptana to start Aptana.


If you are unable to start aptana, I have a work-around for that. In Step 11:

for the Command : /home/foo/Aptana/Aptana_IDE_Beta/Aptana

The directory /home/foo/Aptana is the directory where Aptana is installed. If Aptana is installed to some othet directory
you need to feed that path.

Now repeat the Step 12 . Aptana should be starting this time...


Now lets discuss configuring "RadRails" plugin for Aptana...

13. Note that if you are behind a proxy , you need to configure that. To do so,

go to Window -> preferences -> install/update , check the box to the right of "Enable Http proxy connection" and fill the
details and click on "Apply" and "OK"

14. Go to Help -> Software Updates -> Find and Install -> Search for new features to install and click on "Next"

Select the "Ruby on Rails Development Environment" and click on "finish" and just follow the dialogue prompts to complete
the installation.

Now when you restart Aptana you will be able to see RadRails perspective.

15. Like wise you can also install the "Subclipse" just as you have installed "RadRails" in the above step.


Thats all...I think every thing should be working fine now...

If you still face any problems, feel free to post a comment in the blog.

thanks and regards,
Venkat.