<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3260390521541206656</id><updated>2011-12-26T22:57:41.110+06:00</updated><category term='test'/><category term='jquery'/><category term='css'/><category term='java'/><category term='Agile'/><category term='plugin'/><category term='ec2'/><category term='REST'/><category term='Javascript'/><category term='BDD'/><category term='Linux'/><category term='Payment API'/><category term='Amazon'/><category term='optimization'/><category term='Web UI'/><category term='Scrum'/><category term='deployment'/><category term='Object Oriented Design Pattern'/><category term='Ruby on Rails'/><title type='text'>Ashrafuzzaman on Technology</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>34</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-4989554336151197891</id><published>2011-12-26T22:57:00.003+06:00</published><updated>2011-12-26T22:57:41.116+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Customizing rails default generators</title><content type='html'>&lt;h1&gt;

Objective&lt;/h1&gt;
Customizing the template of default rails generators.&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;
How it works&lt;/h1&gt;
&lt;br /&gt;
This is actually pretty simple :) You might get an idea when you take a look &lt;a href="http://github.com/rails/rails/tree/master/railties/lib/rails/generators/erb/scaffold" target="_blank"&gt;here&lt;/a&gt;. There you can find all the templates. Now if you want to customize lets say the &lt;b&gt;index.html.erb&lt;/b&gt;, then in your project directory create the "&lt;b&gt;lib/templates/erb/scaffold/index.html.erb&lt;/b&gt;". After that when you create a scaffold the generator will use your template.&lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;
Reference&lt;/h1&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://guides.rubyonrails.org/generators.html"&gt;http://guides.rubyonrails.org/generators.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railscasts.com/episodes/216-generators-in-rails-3"&gt;http://railscasts.com/episodes/216-generators-in-rails-3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rails/rails/tree/master/railties/lib/rails/generators/erb/scaffold/templates"&gt;https://github.com/rails/rails/tree/master/railties/lib/rails/generators/erb/scaffold/templates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-4989554336151197891?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/4989554336151197891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=4989554336151197891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4989554336151197891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4989554336151197891'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2011/12/customizing-rails-default-generators.html' title='Customizing rails default generators'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-4701370061660061969</id><published>2011-12-18T01:18:00.001+06:00</published><updated>2011-12-18T01:19:29.362+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Jbehave web and web drive</title><content type='html'>&lt;h2&gt;







Objective&lt;/h2&gt;
The purpose of this startup project is to get 
you going with &lt;a href="http://jbehave.org/reference/web/stable/page-objects.html" target="_blank"&gt;jbehave web&lt;/a&gt;(3.4.3) and &lt;a href="http://seleniumhq.org/projects/webdriver/" target="_blank"&gt;WebDrive&lt;/a&gt;. In this example we do a 
simple and basic task.&lt;br /&gt;
&lt;div class="wikistyle"&gt;
&lt;ul&gt;
&lt;li&gt;Load a website&lt;/li&gt;
&lt;li&gt;Click on a link&lt;/li&gt;
&lt;li&gt;And test if the redirected page is where we want to be&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;







Required libraries&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://jbehave.org/reference/downloads/web/bin/stable"&gt;JBehaveWeb&lt;/a&gt; - Add all the jars from lib folder&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://selenium.googlecode.com/files/selenium-java-2.15.0.zip"&gt;Selenium&lt;/a&gt;   -   Add all the jar from lib folder and selenium-java-2.15.0.jar&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/KentBeck/junit/downloads"&gt;JUnit&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
A sample project is uploaded in &lt;a href="https://github.com/ashrafuzzaman/JbehaveWebDriveExample" target="_blank"&gt;github&lt;/a&gt;. It is simple enough to use as a startup project.&lt;br /&gt;
The implementation was done following &lt;a href="http://jbehave.org/reference/web/stable/page-objects.html" target="_blank"&gt;this article&lt;/a&gt;.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-4701370061660061969?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/4701370061660061969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=4701370061660061969' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4701370061660061969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4701370061660061969'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2011/12/jbehave-web-and-web-drive.html' title='Jbehave web and web drive'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-7787328157529906544</id><published>2011-12-18T01:16:00.001+06:00</published><updated>2011-12-18T01:25:30.474+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Jbehave web and page object pattern</title><content type='html'>&lt;h2&gt;








Objective&lt;/h2&gt;
To explain&amp;nbsp; &lt;a href="http://code.google.com/p/selenium/wiki/PageObjects" target="_blank"&gt;page object pattern&lt;/a&gt; and how to use it with &lt;a href="http://jbehave.org/reference/web/stable/page-objects.html" target="_blank"&gt;jbehave web&lt;/a&gt;(3.4.3) and &lt;a href="http://seleniumhq.org/projects/webdriver/" target="_blank"&gt;WebDrive&lt;/a&gt;. &lt;br /&gt;
&lt;div class="wikistyle"&gt;
A sample project is uploaded in &lt;a href="https://github.com/ashrafuzzaman/JbehaveWebDriveExample" target="_blank"&gt;github&lt;/a&gt;. It is simple enough to use as a startup project.&lt;br /&gt;
The implementation was done following &lt;a href="http://jbehave.org/reference/web/stable/page-objects.html" target="_blank"&gt;this article&lt;/a&gt;. The basic is explained there, so in my post I will discuss about the &lt;a href="http://code.google.com/p/selenium/wiki/PageObjects" target="_blank"&gt;page object pattern&lt;/a&gt;, which simplifies the &lt;a href="http://seleniumhq.org/docs/03_webdriver.html" target="_blank"&gt;web drive &lt;/a&gt;implementation.&lt;br /&gt;
&lt;h2&gt;








Page object pattern &lt;/h2&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-I5e6sj-KEnA/TuzjxpgfJHI/AAAAAAAAM9c/4OWJpsULh3E/s1600/Page+object+model.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="280" src="http://1.bp.blogspot.com/-I5e6sj-KEnA/TuzjxpgfJHI/AAAAAAAAM9c/4OWJpsULh3E/s320/Page+object+model.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Each page has a one to one mapping with a java class&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
This might seem to be obvious to map all the pages with a java class. And the navigation from one page to another to map to a method of one object that returns the navigation page object. This approach increases readability in a great extant. Now look at a sample code(just to get an idea).&lt;/div&gt;
&lt;div class="wikistyle"&gt;
&lt;/div&gt;
&lt;div class="wikistyle"&gt;
&lt;pre class="brush: java;"&gt;public class BasicWebSteps {

    private final Pages pages;

    public BasicWebSteps(Pages pages) {
        this.pages = pages;
    }

    @Given("user is on Home page")
    public void userIsOnHomePage(){        
        pages.homePage().open();        
    }

    @When("user clicks on Resume from menu")
    public void userClicksOnResumeLink(){        
        pages.resumePage().open();
    }

    @Then("Resume page is shown")
    public void runStoryPageIsShown(){
        pages.resumePage().assertShown();
    }

}
&lt;/pre&gt;
This increases the readability of the step definition. It encapsulates the logic of navigation, structure of page specific html,&amp;nbsp; page specific assertions for each pages in corresponding classes. This approach follows Single Responsibility Principle and makes a logical separation in the test project.&lt;br /&gt;
Jbehave help you to implement this pattern by providing &lt;a href="http://jbehave.org/reference/web/stable/javadoc/web-selenium/org/jbehave/web/selenium/WebDriverPage.html" target="_blank"&gt;WebDriverPage&lt;/a&gt;. So your parent class of each page might look like,&lt;br /&gt;
&lt;pre class="brush: java;"&gt;public abstract class AbstractPage extends WebDriverPage {
    public AbstractPage(WebDriverProvider driverProvider) {
        super(driverProvider);
    }
    ...
}
&lt;/pre&gt;
And a simple page can be like the following.&lt;br /&gt;
&lt;pre class="brush: java;"&gt;/*
 * Contains page specific
 *   HTML structure
 *   Assertions
 *   Navigation
 */
public class ResumePage extends AbstractPage {

    public ResumePage(WebDriverProvider driverProvider) {
        super(driverProvider);
    }
    
    public void open(){
        findElement(By.linkText("Resume")).click();
    }
    
    public void assertShown() {
        String output = findElement(By.cssSelector("#menu .selected a")).getText();
        assertTrue("Resume menu should be selected", output.contains("Resume"));
    }

}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;








Sample project&lt;/h2&gt;
The sample project can be found &lt;a href="https://github.com/ashrafuzzaman/JbehaveWebDriveExample" target="_blank"&gt;here&lt;/a&gt;. 

 &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-7787328157529906544?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/7787328157529906544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=7787328157529906544' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/7787328157529906544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/7787328157529906544'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2011/12/jbehave-web-and-page-object-pattern.html' title='Jbehave web and page object pattern'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-I5e6sj-KEnA/TuzjxpgfJHI/AAAAAAAAM9c/4OWJpsULh3E/s72-c/Page+object+model.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-2730407062358313515</id><published>2011-12-14T02:25:00.000+06:00</published><updated>2011-12-17T03:29:38.587+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Java Behavior Driven Development BDD</title><content type='html'>&lt;h2&gt;

Objective&lt;/h2&gt;
The purpose of this article is to get you going with &lt;a href="http://jbehave.org/" target="_blank"&gt;jbehave&lt;/a&gt;, an elegant Java based BDD framework. This is a simple &lt;a href="http://jbehave.org/reference/stable/getting-started.html" target="_blank"&gt;example&lt;/a&gt; of powerful  &lt;a href="http://jbehave.org/" target="_blank"&gt;jbehave&lt;/a&gt;. I missed a simple example of jbehave, so &lt;a href="https://github.com/ashrafuzzaman/Simple-jbehave-example" target="_blank"&gt;here&lt;/a&gt; is my effort.&lt;br /&gt;
&lt;h2&gt;


Required libraries&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.blogger.com/goog_244957289"&gt;&lt;/a&gt;&lt;a href="http://commons.apache.org/collections/download_collections.cgi" target="_blank"&gt;commons-collections.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://commons.apache.org/lang/download_lang.cgi" target="_blank"&gt;commons-lang.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://freemarker.sourceforge.net/" target="_blank"&gt;freemarker.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jbehave.org/reference/downloads/bin/stable" target="_blank"&gt;jbehave-core.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://commons.apache.org/io/download_io.cgi" target="_blank"&gt;org.apache.commons.io.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jarvana.com/jarvana/archive-details/com/thoughtworks/paranamer/paranamer/2.4/paranamer-2.4.jar" target="_blank"&gt;paranamer.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jarfinder.com/index.php/jars/versionInfo/431" target="_blank"&gt;plexus-utils.jar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
The project is uploaded in &lt;a href="https://github.com/ashrafuzzaman/Simple-jbehave-example" target="_blank"&gt;github&lt;/a&gt;. It also has the dependency jars with it, so that you can start up soon.&lt;br /&gt;
&lt;h2&gt;





References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jbehave.org/"&gt;http://jbehave.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://christophertownson.com/tag/bdd"&gt;http://christophertownson.com/tag/bdd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ashrafuzzaman/Simple-jbehave-example"&gt;https://github.com/ashrafuzzaman/Simple-jbehave-example&lt;/a&gt;&amp;nbsp; &lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-2730407062358313515?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/2730407062358313515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=2730407062358313515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2730407062358313515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2730407062358313515'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2011/12/java-behavior-driven-development-bdd.html' title='Java Behavior Driven Development BDD'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-6389775196013970748</id><published>2011-12-11T13:46:00.001+06:00</published><updated>2011-12-11T16:21:56.137+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='Web UI'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Project Portfolios engine for Refinery CMS</title><content type='html'>Just added a new kind of &lt;a href="http://github.com/ashrafuzzaman/refinerycms-project-portfolios" target="_blank"&gt;portfolio&lt;/a&gt; to get it running in &lt;a href="https://github.com/resolve/refinerycms/" target="_blank"&gt;RefineryCMS&lt;/a&gt;. Here is &lt;a href="http://www.ashrafuzzaman.com/project_portfolios" target="_blank"&gt;demo&lt;/a&gt;.&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-WyY46x6AaRo/TtSkSR-NrkI/AAAAAAAAM8Q/O9V9CE5_T-M/s1600/Portfolio.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="202" src="http://2.bp.blogspot.com/-WyY46x6AaRo/TtSkSR-NrkI/AAAAAAAAM8Q/O9V9CE5_T-M/s320/Portfolio.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Project portfolio&lt;/td&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Ms5K3O6qejg/TtSkTyie_JI/AAAAAAAAM8c/KVTxVYLUZ1U/s1600/Portfolio+popup.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="191" src="http://2.bp.blogspot.com/-Ms5K3O6qejg/TtSkTyie_JI/AAAAAAAAM8c/KVTxVYLUZ1U/s320/Portfolio+popup.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Project details popup&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-6389775196013970748?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/6389775196013970748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=6389775196013970748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6389775196013970748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6389775196013970748'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2011/12/project-portfolios-engine-for-refinery.html' title='Project Portfolios engine for Refinery CMS'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-WyY46x6AaRo/TtSkSR-NrkI/AAAAAAAAM8Q/O9V9CE5_T-M/s72-c/Portfolio.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-1333781801012745633</id><published>2010-06-16T02:43:00.000+06:00</published><updated>2011-12-11T16:22:29.692+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Faqs plugin for Refinery CMS</title><content type='html'>&lt;a href="http://refinerycms.com/" id="sm9d" title="Refinery"&gt;Refinery&lt;/a&gt; is one of the rails CMS that allows people to extend the CMS and build custom plugin on that. The plugins are easy to include and maintain.&lt;br /&gt;
&lt;div&gt;
Faqs are one of the essential part for most of the web applications. So I build a plugin for &lt;a href="http://refinerycms.com/" id="jlwe" title="Refinery"&gt;refinery&lt;/a&gt;. The project is kept on &lt;a href="http://github.com/ashrafuzzaman/refinerycms-faqs" id="k9:6" title="github"&gt;github&lt;/a&gt;. Follow the following scripts to include the plugin.&lt;/div&gt;
&lt;br /&gt;
&lt;pre class="brush: plain;"&gt;script/plugin install git://github.com/ashrafuzzaman/refinerycms-faqs.git
rake refinery:faqs:install
&lt;/pre&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-1333781801012745633?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/1333781801012745633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=1333781801012745633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/1333781801012745633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/1333781801012745633'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2010/06/faqs-plugin-for-refinery-cms.html' title='Faqs plugin for Refinery CMS'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-578299425811889109</id><published>2009-12-24T03:00:00.006+07:00</published><updated>2011-12-11T18:45:55.667+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Payment API'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Implementing Payson API Integration 1.0 in Ruby</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
To do payment using &lt;a href="http://api.payson.se/" title="Payson API integration 1.0"&gt;Payson API integration 1.0&lt;/a&gt; you need to follow 3 steps.&lt;br /&gt;
&lt;div&gt;
&lt;div id="vwze" style="text-align: left;"&gt;
&lt;ol&gt;
&lt;li&gt;Request to &lt;b&gt;initiate a pay request&lt;/b&gt; (in return it will send you back a &lt;b&gt;token&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;Redirect client to Payson site &lt;b&gt;using that token&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;After client completes the payment, Payson will redirect the client back to your site and you can check the payment status and update status of payment on your application&lt;/li&gt;
&lt;/ol&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://api.payson.se/Images/multiple.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="232" src="http://api.payson.se/Images/multiple.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Payson api cycle&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;

Plugin used&lt;/h3&gt;
&lt;div&gt;
&lt;a href="http://rest-client.heroku.com/rdoc/" id="h0l_" title="RestClient"&gt;RestClient&lt;/a&gt; is nice API to handle http request  and response.&lt;/div&gt;
&lt;h3&gt;

Step 1 (Request to initiate a pay request)&lt;/h3&gt;
&lt;div&gt;
To be able to use &lt;a href="http://api.payson.se/" id="sybe" style="color: #551a8b;" title="Payson API integration 1.0"&gt;Payson API integration&lt;/a&gt; you must have,&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;AgentID&lt;/b&gt;:  XXXX&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;b&gt;MD5-key&lt;/b&gt;: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
For a &lt;b&gt;pay initiate request&lt;/b&gt; you can see the specification &lt;a href="http://api.payson.se/#title7" id="gpn3" title="here"&gt;here&lt;/a&gt;. Before you integrate the API in your application you can make a curl http call just to check if every thing works. &lt;/div&gt;
&lt;/div&gt;
&lt;pre class="brush: bash;"&gt;curl -H "PAYSON-SECURITY-USERID:XXXX" \
-H "PAYSON-SECURITY-PASSWORD:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" \
-d "receiverList.receiver(0).email=test@gmail.com&amp;amp;receiverList.receiver(0).amount=10&amp;amp;returnUrl=http://localhost:3000/payson_return/56&amp;amp;cancelUrl=http://localhost:3000/payson_cancel/56&amp;amp;memo=test&amp;amp;senderEmail=sender@gmail.com&amp;amp;senderFirstName=A.K.M.&amp;amp;senderLastName=Ashrafuzzaman" https://api.payson.se/1.0/Pay/ -o payson.out
&lt;/pre&gt;
Here PAYSON-SECURITY-USERID is &lt;b&gt;AgentID&lt;/b&gt; and  PAYSON-SECURITY-PASSWORD &lt;b&gt;MD5-key&lt;/b&gt;. And as you can see PAYSON-SECURITY-USERID and PAYSON-SECURITY-PASSWORD (the authentication fields) will have to be send in the &lt;b&gt;headers of the request&lt;/b&gt;. Now it should return a message which looks like,
&lt;br /&gt;
&lt;pre class="brush: bash;"&gt;responseEnvelope.ack=SUCCESS&amp;amp;responseEnvelope.timestamp=2009-11-15T17%3a14%3a03&amp;amp;responseEnvelope.version=1.0&amp;amp;TOKEN=4ecce14b-a4c7-4990-9814-db8aa2e97553&lt;/pre&gt;
&lt;div&gt;
The response will contain a token which will be used to do the &lt;b&gt;pay request&lt;/b&gt;.&lt;/div&gt;
Now let us see the ruby version of the curl request,
&lt;br /&gt;
&lt;div&gt;
&lt;pre class="brush: ruby;"&gt;params_list = { 'receiverList.receiver(0).email' =&amp;gt; reciever_email,
  'receiverList.receiver(0).amount' =&amp;gt; recieving_amount,
  'receiverList.receiver(1).email' =&amp;gt; more_receiver_email, #you can send money to more then one account
  'receiverList.receiver(1).amount' =&amp;gt; more_receive_amount,
  'returnUrl' =&amp;gt; callback_url,
  'cancelUrl' =&amp;gt; cancel_url,
  'memo' =&amp;gt; description,
  'senderEmail' =&amp;gt; sender_email,
  'senderFirstName' =&amp;gt; first_name,
  'senderLastName' =&amp;gt; last_name }

header_list = {'PAYSON-SECURITY-USERID' =&amp;gt; 'XXXX', 'PAYSON-SECURITY-PASSWORD' =&amp;gt; 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'}

response = RestClient.post 'https://api.payson.se/1.0/Pay/', params_list, header_list
&lt;/pre&gt;
&lt;h3&gt;

Step 2 (Redirect client to Payson site)&lt;/h3&gt;
&lt;div&gt;
Now parse the response and redirect to Payson site for client to complete the payment. &lt;/div&gt;
&lt;pre class="brush: ruby;"&gt;response_hash = parse_response(response)

if response_hash['responseEnvelope.ack'] == 'SUCCESS'
  logger.info "Payson pay response #{response}"
  @signup.payson_token = response_hash['TOKEN']
  @signup.save!
  redirect_to "https://www.payson.se/PaySecure?token=#{response_hash['TOKEN']}"
elsif response_hash['responseEnvelope.ack'] == 'FAILURE'
  redirect_to @signup.event.home_path
end&lt;/pre&gt;
&lt;div&gt;
This will redirect to Payson paysecure page. And client will complete the payment which will redirect the client back to &lt;span style="font-family: 'Courier New';"&gt;returnUrl. If the client cancels the payment then he will be redirected to cancel url.&lt;/span&gt;&lt;/div&gt;
&lt;h3&gt;

Step 3 (complete the process)&lt;/h3&gt;
&lt;div&gt;
Now it is time to nail it ;)&lt;/div&gt;
&lt;div&gt;
In the return action you should check that the payment is done.&lt;/div&gt;
&lt;pre class="brush: ruby;"&gt;response = RestClient.get "https://api.payson.se/1.0/PaymentDetails?token=#{signup.payson_token}",
              {'PAYSON-SECURITY-USERID' =&amp;gt; 'XXXX', 'PAYSON-SECURITY-PASSWORD' =&amp;gt; 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'}
response_hash = parse_response(response)
@signup.payson_params = response_hash
@signup.payson_status = response_hash['responseEnvelope.status']
@signup.save!
if @signup.payson_status == Payment::PaysonClient::COMPLETED
  confirm_signup
else
  @signup.fail!
  ErrorNotifier.deliver_notification("Payment failed with status #{@signup.payson_status} for signup #{@signup.inspect}")
end
&lt;/pre&gt;
&lt;div&gt;
You can check the reference for pay details request &lt;a href="http://api.payson.se/#title8" id="yzr1" title="here"&gt;here&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-578299425811889109?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/578299425811889109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=578299425811889109' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/578299425811889109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/578299425811889109'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/12/implementing-payson-api-integration-10.html' title='Implementing Payson API Integration 1.0 in Ruby'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-3795405109595625710</id><published>2009-08-08T23:44:00.004+07:00</published><updated>2009-08-08T23:55:21.318+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Tips on writing browser compatible css</title><content type='html'>&lt;p&gt;Writing browser compatible css is a difficult job for people with less experience in css. Specially Internet Explorer make things interesting(or gives you headache, what ever you prefer ;) ). As an application grows it becomes more and more difficult to manage browser compatibility. And as Internet explorer continues to release new versions, it leaves a few time for developers to spare. Some times different browser is needed to tweak differently. It may be the size of the font, padding floating problems etc.&lt;/p&gt;  &lt;p&gt;People then started to use &lt;strong&gt;Conditional Comments &lt;/strong&gt;like bellow to give browser compatibility,&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;!--[if lte IE 6]&amp;gt;
&amp;lt;link rel="stylesheet" type="text/css" href="ie_hacks.css" /&amp;gt;
&amp;lt;![endif]—&amp;gt;&lt;/pre&gt;&lt;p&gt;And there is the !important hack&lt;/p&gt;&lt;p&gt;Normally in CSS whichever rule is specified last takes precedence. However if you use !important after a command then this CSS command will take precedence regardless of what appears after it. This is true for all browsers except IE. Here you can find &lt;a href="http://www.evolt.org/ten-css-tricks-you-may-not-know" target="_blank"&gt;more&lt;/a&gt;.&lt;/p&gt;&lt;pre class="brush: js;"&gt;h1 { font-size: 1.6em !important; font-size: 1.4em; }&lt;/pre&gt;&lt;p&gt;Here IE still takes 1.4em as the font size.&lt;/p&gt;&lt;p&gt;&lt;a href="http://tantek.com/CSS/Examples/" target="_blank"&gt;&lt;b&gt;Tantek&lt;/b&gt;&lt;/a&gt;&lt;b&gt; &lt;/b&gt;&lt;a href="http://www.communitymx.com/content/article.cfm?cid=E0989953B6F20B41"&gt;&lt;b&gt;box model&lt;/b&gt;&lt;/a&gt;&lt;b&gt; hack&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://tantek.com/CSS/Examples/" target="_blank"&gt;Tantek&lt;/a&gt; introduced a &lt;a href="http://tantek.com/CSS/Examples/boxmodelhack.html" target="_blank"&gt;hack&lt;/a&gt; for ie and opera regarding the &lt;a href="http://www.communitymx.com/content/article.cfm?cid=E0989953B6F20B41"&gt;box model problem&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Hybrid Hacking&lt;/strong&gt; defined css as,&lt;/p&gt;&lt;pre class="brush: css;"&gt;#wrapper {
width: 770px;
wid\th: 750px;
}&lt;/pre&gt;&lt;p&gt;It's a legal 'escape' backslash and should be ignored, but when it is inside the property name it is &lt;em&gt;not&lt;/em&gt; ignored by IE5 and IE5.5 for Windows. Instead it causes those browsers to ignore the following "t" character in this case, thus making the property name unreadable to them. Which was explained &lt;a href="http://www.positioniseverything.net/articles/ie7-dehacker.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Then there was the &lt;strong&gt;The Child and Adjacent Sibling Hacks&lt;/strong&gt;, as IE does not understands html&amp;gt;body. Which looks like,&lt;/p&gt;&lt;pre class="brush: css;"&gt;#wrapper {
min-height: 500px; /* IEwin does not support min-height */
height: 500px;
}

html&amp;gt;body #wrapper {
height: auto;
}&lt;/pre&gt;&lt;p&gt;This is discussed more elaborately &lt;a href="http://www.positioniseverything.net/articles/ie7-dehacker.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://centricle.com/ref/css/filters/" target="_blank"&gt;Here&lt;/a&gt; is a list of rule compatibility of browsers which is really useful.&lt;/p&gt;&lt;h4&gt;An easy solution to write css which can easily support different browser&lt;/h4&gt;&lt;p&gt;It is a combination of Javascript and CSS. Here is the Javascript that detects the browser and add a dummy class to body tag.&lt;/p&gt;&lt;pre class="brush: js;"&gt;if ( $.browser.msie &amp;amp;&amp;amp; $.browser.version == "6.0" ) {
$("body").addClass("ie6");
}&lt;/pre&gt;
Although it is written in JQuery, there are plain Javascript &lt;a href="http://www.w3schools.com/js/js_browser.asp" target="_blank"&gt;available&lt;/a&gt;.

&lt;p&gt;So now if your clients browser is IE6 then you already have a dummy class added to you body tag. Now you can write IE6 specific hack easily.&lt;/p&gt;&lt;pre class="brush: js;"&gt;h1 { font-size: 1.6em; }
.ie6 h1 { font-size: 1.4em; }&lt;/pre&gt;&lt;p&gt;It is more readable and you can provide different hack for different browser and versions with this hack.&lt;/p&gt;&lt;h4&gt;References&lt;/h4&gt;&lt;p&gt;&lt;a href="http://www.positioniseverything.net/articles/ie7-dehacker.html"&gt;http://www.positioniseverything.net/articles/ie7-dehacker.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.evolt.org/ten-css-tricks-you-may-not-know"&gt;http://www.evolt.org/ten-css-tricks-you-may-not-know&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-3795405109595625710?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/3795405109595625710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=3795405109595625710' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/3795405109595625710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/3795405109595625710'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/08/tips-on-writing-browser-compatible-css.html' title='Tips on writing browser compatible css'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-776337242488160169</id><published>2009-08-06T20:43:00.001+07:00</published><updated>2009-08-07T11:03:09.512+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Using acts_as_auditable for keeping history for model activities in rails</title><content type='html'>&lt;p&gt;Keeping change history for important models are crucial for some application. And &lt;a href="http://github.com/joshuaclayton/acts_as_auditable/tree/master" target="_blank"&gt;acts_as_auditable&lt;/a&gt; provides a clean implementation for keeping history.&lt;/p&gt;&lt;h4&gt;Install&lt;/h4&gt;&lt;p&gt;1. Download &lt;a href="http://github.com/joshuaclayton/acts_as_auditable/tree/master" target="_blank"&gt;acts_as_auditable&lt;/a&gt; and put in your vendor folder&lt;/p&gt;&lt;p&gt;2. run &lt;/p&gt;&lt;pre class="brush: bash;"&gt;ruby script\generate audit&lt;/pre&gt;&lt;p&gt;from your application directory. Which will generate a migration script to create audits table and a model named Audit.&lt;/p&gt;&lt;h4&gt;Expectation&lt;/h4&gt;&lt;p&gt;1. User model that inherits from ActiveRecord::Base with an instance method of auditor_name(it is required as it stores the auditors name as well as the auditor’s reference for keeping history).&lt;/p&gt;&lt;p&gt;2. A property named auditor(which will be injected in the model where you are using audit) should be prefilled with the user object who is changing the model.&lt;/p&gt;&lt;p&gt;3. Now you can use audit in your model as,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;audit :when =&gt; :before_update,
      :if =&gt; lambda {|work_item| work_item.changed? },
      :with_message =&gt; lambda { |post| 'Something changed :)' }&lt;/pre&gt;&lt;p&gt;Here&lt;/p&gt;&lt;pre class="brush: text;"&gt;:when         =&gt; any active record callbacks (like :before_create)
:if           =&gt; provide a condition which will be checked to create the audit
:with_message =&gt; the message to be stored&lt;/pre&gt;&lt;p&gt;Well that’s about it to use &lt;a href="http://github.com/joshuaclayton/acts_as_auditable/tree/master" target="_blank"&gt;acts_as_auditable&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Implementing in real project&lt;/h4&gt;The challenge that I faced is to create a human readable message for model and make it maintainable.&lt;p&gt;I actually used audit like,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;audit :when =&gt; :before_update,
      :if =&gt; lambda {|work_item| work_item.changed? },
      :with_message =&gt; lambda { |work_item| work_item.audit_message }&lt;/pre&gt;&lt;p&gt;Now here is the code to generate the message.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;def audit_message
  history_text = ''
  self.changes.each do |field, change|
    history_text += "#{field.humanize} changed from '#{change[0]}' to '#{change[1]}'\n" unless field.ends_with?('_id')
  end

  history_text += audit_message_for('project_id', Project, :name, 'project')
  history_text += audit_message_for('sprint_id', Sprint, :name, 'sprint')
  history_text += audit_message_for('responsible_person_id', User, :full_name, 'responsible_person', 'Responsible Person')
  history_text += audit_message_for('release_id', Release, :name, 'release')
  history_text += audit_message_for('point_id', Point, :name, 'point')

  return history_text
end&lt;/pre&gt;&lt;p&gt;And here is the nasty part that at least cleans the audit message implementation. It helps to generate audit message for reference objects.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;private
# Used for making the audit text readable
#
# ==== Parameters
#
# * +field+ - The database field to inspect changes
# * +klass+ - The class for the referenced object
# * +klass_property+ - The property of the object which will be readable to store audit data
# * +readable_name+ - readable name for the class. By default it is klass.to_s
#
# ==== Returns
# The audit text for that field.
# If there is no change in the field then empty string is returned
def audit_message_for(field, klass, klass_property, belongs_to, readable_name = klass.to_s)
  history_text = ''
  seperator = '\n'
  #as this is done with reflaction, catching exeptions for protection
  begin
    if self.send("#{field}_changed?")
      field_was = "#{field}_was"

      changed_from = klass.find(self.send(field_was)).send(klass_property) unless self.send(field_was) == nil
      changed_to   = self.send(belongs_to).send(klass_property) unless self.send(field) == nil

      if self.send(field_was) == nil
        history_text = "#{readable_name} assigned to '#{changed_to}'#{seperator}"
      elsif self.send(field) == nil
        history_text = "Removed #{readable_name} from '#{changed_from}'#{seperator}"
      else
        history_text = "#{readable_name} changed from '#{changed_from}' to '#{changed_to}'#{seperator}"
      end
    end
  rescue Exception =&gt; ex
    logger.error "Error #{ex.to_s}"
  end

  return history_text
end&lt;/pre&gt;&lt;p&gt;Another thing to consider is assigning the auditor before saving the history. It is cleaner if you define a method named auditor. That is how you can avoid assigning to that attribute.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;def auditor
  return self.new_record? ? self.creator : self.updator
end
&lt;/pre&gt;&lt;p&gt;But for implementing like this you need to modify some code in the library. Open the vendor\plugins\acts_as_auditable\lib\shooter\acts\auditable.rb and remove the line,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;attr_accessor :auditor
&lt;/pre&gt;&lt;p&gt;Otherwise your method will be overwritten.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-776337242488160169?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/776337242488160169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=776337242488160169' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/776337242488160169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/776337242488160169'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/08/using-actsasauditable-for-keeping.html' title='Using acts_as_auditable for keeping history for model activities in rails'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-2384714186843114368</id><published>2009-07-26T16:33:00.001+07:00</published><updated>2009-07-26T16:45:45.290+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='Scrum'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Give partial test release and get early feedback</title><content type='html'>&lt;p&gt;In &lt;a href="http://www.scrumpad.com"&gt;scrumpad&lt;/a&gt; project we give our test rollout on Tuesday and production rollout on Wednesday(if every thing goes well :) ). But soon we realized that one day after test deployment is not enough to provide&amp;#160; a smooth production delivery, as we need to work on client feedback and issues after test rollout. This becomes a bigger issue if the client is in the opposite time zone, which gives us less time to communicate.&lt;/p&gt;  &lt;p&gt;To resolve this issue we introduced partial test rollout with in the sprint, which helped us a big time. This way we get early feedback from client, which makes us more efficient in responding.&lt;/p&gt;  &lt;h4&gt;Benefits&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;Early feedback reduces risk on successful production delivery&lt;/li&gt;    &lt;li&gt;Reduces the scope of communication gap between client and developers&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Things to keep an eye on&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;With in the sprint the code base can be unstable. To resolve this we predefine a date for partial test deployment, so that people are prepared and commit only stable code on that day. Before test rollout we run all the test codes and always keep a sharp eye on the continuous integration report so that our code base is kept stable.&lt;/li&gt;    &lt;li&gt;Be brave to give partial test rollout. Some functionality might break(so let the client be aware of this) but the early feedback will surely make your life easy :) . So iterate test deploy with in the iteration.&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-2384714186843114368?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/2384714186843114368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=2384714186843114368' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2384714186843114368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2384714186843114368'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/07/give-partial-test-release-and-get-early.html' title='Give partial test release and get early feedback'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-2170049291231539780</id><published>2009-07-23T15:55:00.002+07:00</published><updated>2009-08-08T21:14:06.889+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Looking into rails named_scope</title><content type='html'>&lt;h3&gt;named scope?&lt;/h3&gt;  &lt;p&gt;Nick Kallen’s &lt;a href="http://pivots.pivotallabs.com/users/nick/blog/articles/284-hasfinder-it-s-now-easier-than-ever-to-create-complex-re-usable-sql-queries"&gt;has_finder&lt;/a&gt; plugin has found it’s way into rails 2.x as named_scope. Named scope is all about scoping or narrowing the database query.&lt;/p&gt;  &lt;p&gt;Let me go through an example to make things easy.&lt;/p&gt;  &lt;pre class="brush: ruby;"&gt;class Post &lt; ActiveRecord::Base
  belongs_to :author,   :class_name =&gt; 'User'
  has_many   :comments, :dependent  =&gt; :destroy

  named_scope :published,   :conditions =&gt; { :is_published =&gt; true }
  named_scope :draft,       :conditions =&gt; { :is_published =&gt; false }
  named_scope :has_comment, :conditions =&gt; [ 'comments_count &gt; 0' ]

  named_scope :recent,    lambda { |*date| {:conditions =&gt; { :created_at =&gt; date.first || 1.weeks.ago } } }
  named_scope :before,    lambda{ |date| { :conditions =&gt; ['created_at &gt; ?',  date] } }
end&lt;/pre&gt;You can &lt;strong&gt;scope&lt;/strong&gt; your query and make it more readable.
&lt;pre class="brush: ruby;"&gt;Post.published #equivalant to Post.all.published&lt;/pre&gt;&lt;p&gt;You can also &lt;strong&gt;scope on finder&lt;/strong&gt; methods like,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;Post.find(:all, :conditions =&gt; { :created_at =&gt; 1.weeks.ago }).published&lt;/pre&gt;&lt;p&gt;You can use &lt;strong&gt;finder on scope &lt;/strong&gt;like,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;Post.published.find(:all, :conditions =&gt; { :created_at =&gt; 1.weeks.ago })&lt;/pre&gt;&lt;p&gt;Even &lt;strong&gt;scope on the relations&lt;/strong&gt;.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;class Comment &lt; ActiveRecord::Base
  belongs_to :post
  belongs_to :author, :class_name =&gt; 'User'

  named_scope :unread, :conditions =&gt; {:is_unread =&gt; true}
  named_scope :read, :conditions =&gt; {:is_unread =&gt; false}
end&lt;/pre&gt;&lt;p&gt;So now you can write like,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;Post.find(id).comments.unread&lt;/pre&gt;&lt;h4&gt;Chaining&lt;/h4&gt;&lt;p&gt;Now would not it be wonderful if you could write like &lt;strong&gt;“Get all posts which are recently published”&lt;/strong&gt; and it would return you what it means.&lt;/p&gt;&lt;p&gt;Using named_scope that dream will come true ;). You can finally write code like this,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;Post.recent.published&lt;/pre&gt;&lt;p&gt;You can chain up to your hearts content ;). You can do all sort of combination like,&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;Post.recent.published.has_comment&lt;/pre&gt;&lt;p&gt;Which will return you posts which are recently published and has comments. See how much readable the code has become.&lt;/p&gt;&lt;h4&gt;Passing Arguments&lt;/h4&gt;&lt;p&gt;You can pass arguments using lambda.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;Post.published.before(1.days.ago)&lt;/pre&gt;&lt;h4&gt;Named Scope Extensions&lt;/h4&gt;&lt;p&gt;Extend named scope and add methods to it.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;class Post &lt; ActiveRecord::Base
  named_scope :draft,       :conditions =&gt; { :is_published =&gt; false } do
    def publish
      each { |post| post.update_attribute(:is_published, true) }
    end
  end
end&lt;/pre&gt;&lt;pre class="brush: ruby;"&gt;Post.recent.draft.publish&lt;/pre&gt;&lt;p&gt;This will find all recent draft posts and publish them.&lt;/p&gt;&lt;h4&gt;Anonymous Scopes&lt;/h4&gt;&lt;p&gt;Creating named scopes on the fly.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;# Store named scopes
published = Post.scoped(:conditions =&gt; { :is_published =&gt; true })
recent    = Post.scoped(:conditions =&gt; { :created_at =&gt; 1.weeks.ago })

# Which can be combined
recent_published = recent.published&lt;/pre&gt;&lt;h3&gt;Why use named scope?
  &lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Increases readability
  &lt;/li&gt;&lt;li&gt;Reduces number of queries as it can be chained
  &lt;/li&gt;&lt;li&gt;Very helpful for dynamic queries(like using pagination or dynamic filter)&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;A common issue&lt;/h3&gt;&lt;p&gt;Named scope is a class methods. And you should always be very careful for class methods. Here is an example where most people does it wrong.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;class Post &lt; ActiveRecord::Base
  belongs_to :author,   :class_name =&gt; 'User'
  has_many   :comments, :dependent  =&gt; :destroy
  
  named_scope :recent,  :conditions =&gt; { :created_at =&gt; 1.weeks.ago } 
end&lt;/pre&gt;&lt;p&gt;Now I can call &lt;strong&gt;Post.recent&lt;/strong&gt; and expect to get all Posts within one week. But in times you will find that this query is starting to give &lt;strong&gt;&lt;font color="#ff0000"&gt;wrong results&lt;/font&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Why???!!!&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Named scope is a class method and so &lt;strong&gt;1.weeks.ago&lt;/strong&gt; is evaluated when the class was loaded. Now it does not matter when you call the named scope it will always run the query with the same created_at date. We also made this mistake :( and learned from it :)&lt;/p&gt;&lt;p&gt;A lambda block is not evaluated when the class is loaded. So there is a work around it.&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;class Post &lt; ActiveRecord::Base
  belongs_to :author,   :class_name =&gt; 'User'
  has_many   :comments, :dependent  =&gt; :destroy

  named_scope :recent,    lambda { |*date| {:conditions =&gt; { :created_at =&gt; date.first || 1.weeks.ago } } }
end&lt;/pre&gt;&lt;p&gt;Taking the lambda input like this will give you flexibility of not providing the parameter at all. For now ruby does not provide facility to take default parameter for lambda.&lt;/p&gt;&lt;h3&gt;Deep inside named scope&lt;/h3&gt;The implementation of Named scope is a beauty of rails. Although the result that named scope produces seems like an Array, but actually it is not an Array but a simulation of an Array. Calling a named scope over a finder object actually returns a ActiveRecord:NamedScope:Scope object. When we chain scopes on that object, appends the query logic in the scope object. The query is not evaluated until an Array method(like each, first, last) etc is called. And when these Array methods are called the scope object then evaluates the query and delegates the method which was called as an array to the real array that has been evaluated. Now you can not chain the scope any more, as it is already been evaluated. That is how the named scope magic works in ruby on rails.
&lt;h3&gt;Reference&lt;/h3&gt;&lt;p&gt;&lt;a href="http://ryandaigle.com/articles/2008/3/24/what-s-new-in-edge-rails-has-finder-functionality"&gt;http://ryandaigle.com/articles/2008/3/24/what-s-new-in-edge-rails-has-finder-functionality&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://railscasts.com/episodes/108-named-scope"&gt;http://railscasts.com/episodes/108-named-scope&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/named_scope"&gt;http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/named_scope&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-2170049291231539780?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/2170049291231539780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=2170049291231539780' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2170049291231539780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2170049291231539780'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/07/looking-into-rails-namedscope.html' title='Looking into rails named_scope'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-8593513284336512162</id><published>2009-07-17T21:30:00.001+07:00</published><updated>2009-07-18T01:26:19.144+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Some Css and Javascripts optimization tips</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;There are so many aspect for optimizing the performance of a web application, that some times people tends to forget about Javascript and Css.&lt;/p&gt;  &lt;p&gt;Yahoo developers experienced that, 80% of the end-user response time is spent on the front-end. Most of the time browser is busy downloading images, stylesheets, scripts, Flash, etc. &lt;a href='http://developer.yahoo.com/performance/rules.html'&gt;Here&lt;/a&gt; you can find the details.&lt;/p&gt;  &lt;p&gt;But there are improvement opportunities in these areas to improve the over all performance of the application. &lt;/p&gt;  &lt;p&gt;Mostly we concentrate on some basic criteria&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href='#caching'&gt;Caching&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href='#minify'&gt;Minifying Javascript and Css&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href='#reduce_file'&gt;Reducing number of files&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;&lt;a href='#' name='caching'&gt;Caching&lt;/a&gt;&lt;/h3&gt;  &lt;p&gt;Caching is great and browser gives you for free :). But should all our css and Javascripts should be cached??&lt;/p&gt;  &lt;p&gt;Actually no!! Because some times browsers cache too much(specially Internet Explorer). You want the client to get the latest files if the file is changed.&lt;/p&gt;  &lt;p&gt;So we need to identify the files that changes and files that do not change(library files,  like jquery, prototype etc). We expect library files to get cached and custom files that changes a lot, not to be cached. We can skip caching by passing a random query string like,&lt;/p&gt;  &lt;pre class='brush: xml;'&gt;&amp;lt;script type="text/javascript" src="scripts/default.js?rand=1"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;That random number can be generated from the server side while serving the page (which is a built in facility for rails).&lt;br/&gt;Now for common libraries(jQuery, protopye) we should use Google API for 2 reasons&lt;br/&gt;&lt;ol&gt;&lt;li&gt;It grabs the library from the closest location it can get. So it loads faster. &lt;/li&gt;&lt;li&gt;It frees your server from serving the library file, so that your server can serve more files instead. &lt;/li&gt;&lt;/ol&gt;This is how you can use &lt;a target='_blank' href='http://code.google.com/apis/ajax/documentation/#GoogleLoad'&gt;Google API&lt;/a&gt; to load popular Javascript libraries.&lt;br/&gt;&lt;pre class='brush: xml;'&gt;&amp;lt;script type="text/javascript" src="http://www.google.com/jsapi"&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;script type="text/javascript"&amp;gt;&amp;lt;br /&amp;gt;  google.load("jquery", "1.3.2");&amp;lt;br /&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;h3&gt;&lt;a href='#' name='minify'&gt;Minifying Javascript and Css&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;According to &lt;a href='http://developer.yahoo.com/performance/'&gt;Yahoo!'s Exceptional Performance Team&lt;/a&gt;, 40% to 60% of Yahoo!'s users have an empty cache experience and about 20% of all page views are done with an empty cache (see &lt;a href='http://yuiblog.com/blog/2007/01/04/performance-research-part-2/'&gt;this article by Tenni Theurer on the YUIBlog for more information on browser cache usage&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;So surely you want to minify all your javascripts and css on your production server. There are some nice online Javascript and css packer which actually does the trick.&lt;/p&gt;&lt;h4&gt;Javascript&lt;/h4&gt;&lt;p&gt;&lt;a href='http://jscompress.com/'&gt;http://jscompress.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href='http://dean.edwards.name/packer/'&gt;http://dean.edwards.name/packer/&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Css&lt;/h4&gt;&lt;p&gt;&lt;a href='http://www.cssoptimiser.com/'&gt;http://www.cssoptimiser.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href='http://flumpcakes.co.uk/css/optimiser/'&gt;http://flumpcakes.co.uk/css/optimiser/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I know what you are thinking. You can’t go to web and pack all your css and Javascripts all the time you deploy, specially if you are following Agile and deploying your code after every 2 weeks.&lt;/p&gt;&lt;p&gt;There are platform specific implementations to resolve this problem. For rails we can use &lt;a href='http://maintainable.com/articles/minifying_your_rails_javascript'&gt;this&lt;/a&gt; to minify and pack javascripts and reduce number of Javascripts.&lt;/p&gt;&lt;p&gt;You can use yahoo compressor written in Java, so you can run that in any platform.&lt;/p&gt;&lt;p&gt;&lt;a href='http://developer.yahoo.com/yui/compressor/#work'&gt;http://developer.yahoo.com/yui/compressor/#work&lt;/a&gt;&lt;/p&gt;&lt;p&gt;There is another implementation by &lt;a href='mailto:douglas@crockford.com'&gt;Douglas Crockford&lt;/a&gt;,&lt;/p&gt;&lt;p&gt;&lt;a href='http://crockford.com/javascript/jsmin'&gt;http://crockford.com/javascript/jsmin&lt;/a&gt;&lt;/p&gt;&lt;p&gt;We can add necessary commands to our deployment script, so that after or before deployment the compressor is run.&lt;/p&gt;&lt;h3&gt;&lt;a href='#' name='reduce_file'&gt;Reducing number of files&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Web servers can not serve a lot of files consecutively. There are limitation for browsers as well. If you watch your site with firebug net inspection, you will see that a lot of file calls which are not called parallely. So reduction in number of files served can improve the performance of the web application.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;How can we reduce number of files?&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;There are several ways we can reduce number of files.&lt;/p&gt;&lt;p&gt;1. We can merged css and javascript the way we minified it.&lt;/p&gt;&lt;p&gt;2. Most of the cases we don’t care about the images. As a result the number of images grow rapidly.&lt;/p&gt;&lt;p&gt;There are some nice ways to merge images into one using css background-position property. People call this &lt;strong&gt;css sprite&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;And every one use it to reduce file size as well as number of files.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;If you merge some images into one, then size is actually reduced. Because other then the picture information every image maintains a color template. If some images are merged then a super set of color template is generated which reduces the total size of the image then the sum of the size of individuals.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Here are some nice examples&lt;/p&gt;&lt;p&gt;&lt;a href='http://www.smashingmagazine.com/2009/04/27/the-mystery-of-css-sprites-techniques-tools-and-tutorials/'&gt;http://www.smashingmagazine.com/2009/04/27/the-mystery-of-css-sprites-techniques-tools-and-tutorials/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href='http://www.alistapart.com/articles/sprites'&gt;http://www.alistapart.com/articles/sprites&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href='http://css-tricks.com/css-sprites/'&gt;http://css-tricks.com/css-sprites/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href='http://spritegen.website-performance.org/'&gt;Here&lt;/a&gt; is a site that generates css sprite.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-8593513284336512162?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/8593513284336512162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=8593513284336512162' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8593513284336512162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8593513284336512162'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/07/some-css-and-javascripts-optimization.html' title='Some Css and Javascripts optimization tips'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-2941949805808032065</id><published>2009-07-09T12:14:00.002+07:00</published><updated>2009-08-08T22:41:49.954+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Rails logger configuration and log level in production environment</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;p&gt;In production environment, it not feasible to use one log file forever. So people use log that rolls over, depending on file size or time etc.&lt;/p&gt;  &lt;p&gt;If we want to roll over the log file, we can define our custom logger using the following code in the configuration(in config/environments/production.rb).&lt;/p&gt;  &lt;pre class="brush: ruby;"&gt;config.logger = Logger.new(config.log_path, 50, 5242880)&lt;/pre&gt;&lt;a href="http://rails.noobkit.com/show/ruby/ruby/standard-library/logger/new.html"&gt;Here&lt;/a&gt; is the doc for instantiating Logger. The params are as follows.
&lt;pre class="brush: ruby;"&gt;Logger.new(name, shift_age = 7, shift_size = 1048576)&amp;lt;br /&amp;gt;Logger.new(name, shift_age = 'weekly')&lt;/pre&gt;Another thing that we need to set for the production is the log level. We do not need to log the query generated by active record or logs that are in debug level.
So we can define the log level as follows.
&lt;pre class="brush: ruby;"&gt;config.logger = Logger.new(config.log_path, 50, 5242880)&amp;lt;br /&amp;gt;config.logger.level = Logger::INFO&lt;/pre&gt;But if you are using the default log which rails offers by default, you can set the log level as,
&lt;pre class="brush: ruby;"&gt;config.log_level = :info&lt;/pre&gt;You can find the rails environment configuration cheat sheet &lt;a href="http://glu.ttono.us/articles/2006/05/22/configuring-rails-environments-the-cheat-sheet"&gt;here&lt;/a&gt;.

&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-2941949805808032065?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/2941949805808032065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=2941949805808032065' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2941949805808032065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2941949805808032065'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/07/rails-logger-configuration-and-log.html' title='Rails logger configuration and log level in production environment'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-1505939156213676392</id><published>2009-07-08T14:01:00.001+07:00</published><updated>2009-08-08T22:44:21.750+07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Some of the useful way of using fixture better</title><content type='html'>&lt;p&gt;&lt;strong&gt;1. &lt;/strong&gt;Using new fixture facilities in rails 2.(&lt;a href="http://railscasts.com/episodes/81-fixtures-in-rails-2-0"&gt;example&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Which will remove the relational fixtures for has_many :through and has_and_belongs_to_many relations.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; It will remove the ids and will give a better way of relating between tables.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. &lt;/strong&gt;Fixtures are read only:     &amp;nbsp;&amp;nbsp; Never modify any existing fixture, unless your database schema has changed.     &amp;nbsp;&amp;nbsp; Which also indicates that we should be very careful when are adding a new fixture. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. &lt;/strong&gt;Another way to identify if the fixture is well written is that they all should be meaningful.     &amp;nbsp;&amp;nbsp; And none of them should look similar. &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; If a different fixture is needed for only 1 or 2 test, then update existing before doing the test.    &amp;nbsp;&amp;nbsp; For an example, &lt;/p&gt;&lt;pre class="brush: ruby;"&gt;should 'assign responsible person to unassigned task' do
    task = tasks(:task_not_started)
    task.users.clear #clear the existing fixture(not creating a new one for that fixture) 

    assign_and_assert_responsible_person(task, users(:login_user))
end
&lt;/pre&gt;This will &lt;strong&gt;reduce the number of fixture&lt;/strong&gt; set and keep them &lt;strong&gt;clean&lt;/strong&gt;.   &lt;p&gt;&lt;strong&gt;4. &lt;/strong&gt;Often we write test codes that involves a lot of fixture.    
&amp;nbsp;&amp;nbsp; Some times when we get test fail, we run through the fixtures, trying to find out which went wrong.    
&amp;nbsp;&amp;nbsp; But instead if we comment our code such a way that the fixture is understood from the test code,    
&amp;nbsp;&amp;nbsp; then that would be even better. Like,
&lt;/p&gt;&lt;pre class="brush: ruby;"&gt;context 'in progress task' do
  setup do
    @task = tasks(:task_in_progress)
    # task -&gt; time_estimates
    #         [ user: login_user, hours_spent: 2, hours_remaining: 8, entry_date: 1.days.ago ]
    #         [ user: developer , hours_spent: 4, hours_remaining: 3, entry_date: Date.today ]
  end

  should 'return hours spent upto' do
    assert_equal(2, @task.hours_spent_upto(1.days.ago))
    assert_equal(6, @task.hours_spent_upto(Date.today))
  end
end
&lt;/pre&gt;&lt;b&gt;5.&lt;/b&gt; Inherit fields, that are less likely to be different for each fixture
&lt;pre class="brush: ruby;"&gt;
backlog_item: &amp;amp;common_backlog_fields
  project_id: scrumpad
  type: Story

bug:
  &lt;&lt;: *common_backlog_fields
  type: Bug
  title: Test Bug
  content: Bug content
  created_at: &lt;%= 10.days.ago.to_s(:db) %&gt;
  updated_at: &lt;%= 3.days.ago.to_s(:db) %&gt;

story:
  &lt;&lt;: *common_backlog_fields
  title: Sample story
  state: &lt;%= WorkItem::COMPLETED %&gt;
  created_at: &lt;%= 10.days.ago.to_s(:db) %&gt;
  updated_at: &lt;%= 2.days.ago.to_s(:db) %&gt;
&lt;/pre&gt;Here we can define the common required fields in backlog_item and use that definition for other fixtures.
The fields can be overwritten by redefining in the fixtures as we did overwritten type for bug.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-1505939156213676392?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/1505939156213676392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=1505939156213676392' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/1505939156213676392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/1505939156213676392'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/07/some-of-useful-way-of-using-fixture.html' title='Some of the useful way of using fixture better'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-4274365717547853361</id><published>2009-05-22T08:00:00.007+06:00</published><updated>2009-06-06T18:58:00.310+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Selenium In Rails with Fixtures</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;  &lt;/p&gt;&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Selenium_%28software%29'&gt;Selenium&lt;/a&gt; is a framework for &lt;a href='http://en.wikipedia.org/wiki/Acceptance_testing'&gt;acceptance testing&lt;/a&gt;, designed for web applications. With &lt;a href='http://en.wikipedia.org/wiki/Selenium_%28software%29'&gt;selenium&lt;/a&gt; you can run your tests on all popular browsers.&lt;/p&gt;  &lt;p&gt;Now a days web applications are consist of a lot of UI logic, animations, ajax calls. Only unit test and functional test does not ensure the stability of your application any more. A small change in Javascript can cause instability in your application. Tiny changes can break the contract of browser compatibility. A simple miss spelled link can give you a nightmare.&lt;/p&gt;  &lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Selenium_%28software%29'&gt;Selenium&lt;/a&gt; gives you the power to run automated acceptance test codes in real browsers. As it supports all popular browsers you can easily test browser compatibility of your application.&lt;/p&gt;  &lt;h4&gt;Key Features&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href='https://addons.mozilla.org/en-US/firefox/addon/2079'&gt;Selenium IDE&lt;/a&gt; provides facility to record test script with ease and export the script to your &lt;a href='http://seleniumhq.org/about/platforms.html#testing-frameworks'&gt;preferred language&lt;/a&gt;(Java, C#, ruby, Perl, PHP etc) &lt;/li&gt;    &lt;li&gt;Write one test script and run in all popular &lt;a href='http://seleniumhq.org/about/platforms.html#testing-frameworks'&gt;browsers and OS&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href='http://selenium-grid.seleniumhq.org/'&gt;Selenium Grid&lt;/a&gt; facilitates to run test codes parallely in multiple server, which pace up the execution of test code. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Setup&lt;/h4&gt;  &lt;p&gt;Install Selenium client&lt;/p&gt;  &lt;pre class='brush: bash; toolbar: true; auto-links: true;'&gt;gem install selenium-client
&lt;/pre&gt;&lt;p&gt;Download Selenium Remote Control from &lt;a href='http://seleniumhq.org/download/'&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;You will need Java installed on your machine to run Selenium Remote Control.&lt;/p&gt;&lt;p&gt;I write a script to start Selenium Remote Control, which is like.&lt;/p&gt;&lt;pre class='brush: bash; toolbar: true; auto-links: true;'&gt;cd E:\selenium\selenium-remote-control-1.0-beta-2\selenium-server-1.0-beta-2&lt;br/&gt;java -jar selenium-server.jar&lt;/pre&gt;&lt;p&gt;Use Firefox and &lt;a href='https://addons.mozilla.org/en-US/firefox/addon/2079'&gt;Selenium IDE&lt;/a&gt;(a Firefox plugin) to capture the actions and convert it to ruby code.&lt;/p&gt;&lt;p&gt;&lt;a href='https://addons.mozilla.org/en-US/firefox/addon/1095'&gt;XPath Checker&lt;/a&gt; and &lt;a href='https://addons.mozilla.org/en-US/firefox/addon/11905'&gt;Fire Finder&lt;/a&gt; are two useful Firefox plugin to find and locate elements using xpath.&lt;/p&gt;&lt;h4&gt;Record actions&lt;/h4&gt;&lt;p&gt;Start Firefox, go to the root url, from where you are going to start test. Go to tools tab and start Selenium IDE.&lt;/p&gt;&lt;p&gt;Now as you browse through the site Selenium IDE will record the actions. After you have finished a scenario, you can stop recording and export test case as ruby file from File menu.&lt;/p&gt;&lt;p&gt;Selenium IDE generates is an old rails style code and it uses old selenium client driver. Here is a sample integration code that uses rails 2.3.2 style and new selenium client driver.Now to run your test code as you have noticed, you need mention the root url of the site you are testing.&lt;br/&gt;&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;require 'test_helper'&lt;br/&gt;require 'selenium/client'&lt;br/&gt;&lt;br/&gt;class PostsIntegrationTest &amp;lt; ActionController::IntegrationTest&lt;br/&gt;  fixtures :all&lt;br/&gt;&lt;br/&gt;  def setup&lt;br/&gt;    @browser = Selenium::Client::Driver.new(&lt;br/&gt;      :host =&amp;gt; "localhost",&lt;br/&gt;      :port =&amp;gt; 4444,&lt;br/&gt;      :browser =&amp;gt; "*firefox",&lt;br/&gt;      :url =&amp;gt; "http://localhost:3000",&lt;br/&gt;      :timeout_in_second =&amp;gt; 60&lt;br/&gt;    )&lt;br/&gt;&lt;br/&gt;    @browser.start_new_browser_session&lt;br/&gt;  end&lt;br/&gt;&lt;br/&gt;  def teardown&lt;br/&gt;    @browser.close_current_browser_session&lt;br/&gt;  end&lt;br/&gt;&lt;br/&gt;  test 'the truth' do&lt;br/&gt;    @browser.open "/posts"&lt;br/&gt;    @browser.click "link=New post", :wait_for =&amp;gt; :page&lt;br/&gt;    @browser.type "post_title", "test"&lt;br/&gt;    @browser.type "post_title", "Testing with Selenium"&lt;br/&gt;    @browser.type "post_body", "bla... bla..."&lt;br/&gt;    @browser.click "post_published"&lt;br/&gt;    @browser.click "post_submit", :wait_for =&amp;gt; :page&lt;br/&gt;    assert_equal "Testing with Selenium", @browser.get_text("xpath=/html/body/p[2]/span")&lt;br/&gt;  end&lt;br/&gt;&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;Here is the trick. Run your application in test environment. So the application will use test database. As test database is prepared automatically by rails, you can use the test fixtures as the input set of you test codes. And it will be automatically reset to the fixture set for each test methods.&lt;h4&gt;How to organize&lt;/h4&gt;&lt;p&gt;&lt;b&gt;1.&lt;/b&gt; &lt;strong&gt;Dry and reuse&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Acceptance test codes are directly dependent on view code. So you need to reuse test codes as much as possible. If you don’t a simple change in view will make you life hell.&lt;/p&gt;&lt;p&gt;&lt;b&gt;2.&lt;/b&gt; &lt;strong&gt;Separate your actions to methods, so that you can reuse&lt;/strong&gt;&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;def login(user_name, password)&lt;br/&gt; @browser.open "/"&lt;br/&gt; @browser.type "user_name", user_name&lt;br/&gt; @browser.type "password", password&lt;br/&gt; @browser.click "css=.btn[name='commit']", :wait_for =&amp;gt; :page&lt;br/&gt;end&lt;br/&gt;&lt;br/&gt;def login_as_developer()&lt;br/&gt; login(users(:developer).user_name, '123')&lt;br/&gt;end&lt;/pre&gt;&lt;p&gt;Now you can call login method to login to the system. And do not put assertions in these methods. This way you can even test the failure path.&lt;/p&gt;&lt;p&gt;&lt;b&gt;3.&lt;/b&gt; Now call these basic methods and do assertion. This will &lt;strong&gt;make your code readable&lt;/strong&gt;.&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;test 'login as a developer with valid credential' do&lt;br/&gt; login_as_developer()&lt;br/&gt; assert_url('/dashboard/show')&lt;br/&gt;end&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Well there is no such thing as assert_url in selenium client to assert the current relative url.You can copy the following code and put it in your test helper.&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;def assert_url(url)&lt;br/&gt; assert_equal(url, @browser.get_location().match(/.+\/\/[^\/]+(.*)/)[1])&lt;br/&gt;end&lt;/pre&gt;&lt;p&gt;&lt;b&gt;4.&lt;/b&gt; Use a different helper file for common methods. Don’t use the common test helper, as selenium test are quit different from unit and functional test of rails.&lt;/p&gt;&lt;p&gt;It does not uses mock request and response. So you 	can not use selenium methods else where. That is why it is better to separate the selenium test helper.&lt;/p&gt;&lt;p&gt;&lt;b&gt;5. Use selenium-client,&lt;/b&gt; so that you can use different wait_for methods, which are very useful. See the documentation &lt;a target='_blank' href='http://selenium-client.rubyforge.org/'&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-4274365717547853361?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/4274365717547853361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=4274365717547853361' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4274365717547853361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4274365717547853361'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/05/selenium-in-rails-with-fixtures.html' title='Selenium In Rails with Fixtures'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-5051385099299496768</id><published>2009-05-12T10:44:00.003+06:00</published><updated>2009-05-12T10:47:38.925+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>A solution for a gem install mysql problem</title><content type='html'>&lt;p&gt;Some times we get an error in linux as follows while running &lt;strong&gt;gem install mysql&lt;/strong&gt;,&lt;/p&gt;  &lt;pre class="brush: bash; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;root@ip-10-251-30-82:/etc/mysql# gem install mysql
Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
     ERROR: Failed to build gem native extension.

/usr/bin/ruby1.8 extconf.rb install mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
     --with-opt-dir
     --without-opt-dir
     --with-opt-include
     --without-opt-include=${opt-dir}/include
     --with-opt-lib
     --without-opt-lib=${opt-dir}/lib
     --with-make-prog
     --without-make-prog
     --srcdir=.
     --curdir
     --ruby=/usr/bin/ruby1.8
     --with-mysql-config
     --without-mysql-config
     --with-mysql-dir
     --without-mysql-dir
     --with-mysql-include
     --without-mysql-include=${mysql-dir}/include
     --with-mysql-lib
     --without-mysql-lib=${mysql-dir}/lib
     --with-mysqlclientlib
     --without-mysqlclientlib
     --with-mlib
     --without-mlib
     --with-mysqlclientlib
     --without-mysqlclientlib
     --with-zlib
     --without-zlib
     --with-mysqlclientlib
     --without-mysqlclientlib
     --with-socketlib
     --without-socketlib
     --with-mysqlclientlib
     --without-mysqlclientlib
     --with-nsllib
     --without-nsllib
     --with-mysqlclientlib
     --without-mysqlclientlib


Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/mysql-2.7 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/mysql-2.7/gem_make.out
root@ip-10-251-30-82:/etc/mysql# gem install mysql -- --with-mysql-config=/etc/mysql/my.cnf
Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
     ERROR: Failed to build gem native extension.&lt;/pre&gt;&lt;p&gt;The solution is simple :)&lt;/p&gt;&lt;p&gt;Just run,&lt;/p&gt;&lt;pre class="brush: bash; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;apt-get install libmysqlclient15-dev libmysqlclient15off zlib1g-dev libmysql-ruby1.8&lt;/pre&gt;&lt;p&gt;Run the following if you do not have mysql installed,&lt;/p&gt;&lt;pre class="brush: bash; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;apt-get install mysql-server-5.0 mysql-client-5.0 libmysqlclient15-dev libmysqlclient15off zlib1g-dev libmysql-ruby1.8&lt;/pre&gt;&lt;p&gt;And then run&lt;/p&gt;&lt;pre class="brush: bash; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"&gt;gem install mysql&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-5051385099299496768?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/5051385099299496768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=5051385099299496768' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/5051385099299496768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/5051385099299496768'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/05/solution-for-gem-install-mysql-problem.html' title='A solution for a gem install mysql problem'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-8851773272707798220</id><published>2009-05-02T22:26:00.005+06:00</published><updated>2009-05-02T22:51:53.223+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Testing model in rails</title><content type='html'>&lt;h4&gt;How we want our test environment&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Isolation of input fixtures, so that changing fixture of one test code will not impact others. &lt;/li&gt;    &lt;li&gt;Easily create input set and reuse existing. &lt;/li&gt;    &lt;li&gt;Readable test code. &lt;/li&gt;    &lt;li&gt;Runs very fast(Slower test codes are run less by developers). &lt;/li&gt;    &lt;li&gt;Write less to test. &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Problems with built in fixture and test helper&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Fixture does not allow to isolate input set. &lt;/li&gt;    &lt;li&gt;No feature of reusability in fixtures causes developer to create unnecessary duplication in fixtures. &lt;/li&gt;    &lt;li&gt;Changes in table definition causes a lot of change in fixture set. &lt;/li&gt;    &lt;li&gt;Fixtures are hidden in different file. So it becomes difficult to trace a test code. &lt;/li&gt;    &lt;li&gt;Fixture is database driven. So even if you do not need a saved instance of an ActiveRecord object, you end up using one. The more the queries get executed, the slower the test code becomes. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://dev.thoughtbot.com/factory_girl/"&gt;Factory girl&lt;/a&gt;, one of the alternate of fixture seems to be the better solution then fixture. And &lt;a href="http://thoughtbot.com/projects/shoulda"&gt;shoulda&lt;/a&gt; makes the life easier for writing test codes.&lt;/p&gt;  &lt;h4&gt;Why factory?&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Isolated input set &lt;/li&gt;    &lt;li&gt;Different build method gives the flexibility to create saved and unsaved instances &lt;/li&gt;    &lt;li&gt;Can easily extend existing factory to create a new one &lt;/li&gt;    &lt;li&gt;Facility to override property and to stub methods to reduce database query &lt;/li&gt;    &lt;li&gt;Increase readability of test codes. &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Why Shoulda?&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;&lt;em&gt;Context &amp;amp; Should blocks&lt;/em&gt;&lt;/strong&gt; - Context and should block provides facilities to do &lt;a href="http://en.wikipedia.org/wiki/Behavior-driven_development"&gt;BDD&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;Assertions&lt;/em&gt;&lt;/strong&gt; - Provides many common and useful assertions &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;Macros&lt;/em&gt;&lt;/strong&gt; - Generate many ActionController and ActiveRecord tests with helpful error messages &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So let’s get some action. Here is a simple test done using &lt;a href="http://thoughtbot.com/projects/factory_girl"&gt;factory&lt;/a&gt; and &lt;a href="http://thoughtbot.com/projects/shoulda"&gt;shoulda&lt;/a&gt;. We will write unit test for User model which looks like the following.&lt;/p&gt;  &lt;pre class="brush: rails; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: false;"&gt;class User &amp;lt; ActiveRecord::Base
 has_many :posts, :order =&amp;gt; 'created_at DESC'
 has_many :comments

 validates_format_of :email, :with =&amp;gt; /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
 validates_uniqueness_of :email

 def display_name
   return "#{first_name} #{last_name}"
 end

 def latest_post
   return self.posts.first
 end
end&lt;/pre&gt;&lt;p&gt;The Post model is,&lt;/p&gt;&lt;pre class="brush: rails; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: false;"&gt;class Post &amp;lt; ActiveRecord::Base
 belongs_to :user
 has_many :comments, :dependent =&amp;gt; :destroy

 validates_presence_of :title
 validates_presence_of :body
end&lt;/pre&gt;&lt;p&gt;And the user factory is,&lt;/p&gt;&lt;pre class="brush: rails; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: false;"&gt;Factory.sequence :email do |n|
 "email#{n}@test.com"
end

Factory.define :user do |u|
 u.first_name 'Ashraf'
 u.last_name  'Zaman'
 #allows you to create different users with different email using the same definition
 u.email { Factory.next(:email) }
end&lt;/pre&gt;&lt;p&gt;Post factory is,&lt;/p&gt;&lt;pre class="brush: rails; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: false;"&gt;Factory.define :post do |p|
 p.title 'A sample post'
 p.body  'This is a sample post'
 p.created_at Time.now
 p.updated_at Time.now
end&lt;/pre&gt;&lt;p&gt;Finally the user model test is,&lt;/p&gt;&lt;pre class="brush: rails; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: false;"&gt;require 'test_helper'

class UserTest &amp;lt; ActiveSupport::TestCase

 should_have_many :posts
 should_have_many :comments
 should_require_unique_attributes :email

 should_not_allow_values_for :email, "ab.cd", "1234@"
 should_allow_values_for :email, "ashrafuzzaman.g2@gmail.com"

 should 'display_name' do
   user = Factory.build(:user, :first_name =&amp;gt; 'Ashraf', :last_name =&amp;gt; 'Zaman')
   assert_equal('Ashraf Zaman', user.display_name)
 end

 context 'Default posts' do
   setup do
     @user = Factory.build(:user, :posts =&amp;gt; [
         Factory.build(:post, :title =&amp;gt; 'Second Post', :created_at =&amp;gt; Time.now),
         Factory.build(:post, :title =&amp;gt; 'First Post', :created_at =&amp;gt; 2.minutes.ago)
       ])
   end

   should 'return latest post' do
     assert_equal('Second Post', @user.latest_post.title)
   end
 end

end&lt;/pre&gt;&lt;p&gt;You can download the demo from &lt;a href="http://demo.ashrafuzzaman.com/rails/RailsUnitTest.zip"&gt;here&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;How factory helped&lt;/h4&gt;&lt;p&gt;To test the display_name I do not need a saved instance, So I used &lt;a href="http://dev.thoughtbot.com/factory_girl/classes/Factory.html#M000009"&gt;Factory.build&lt;/a&gt; to build the model object with out saving it in the database.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; With &lt;a href="http://dev.thoughtbot.com/factory_girl/classes/Factory.html#M000009"&gt;Factory.build&lt;/a&gt; you can create an unsaved model instance from the factory prototype. It is very useful for testing model logic.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Some attributes of user prototype are intentionally redefined to increase the readability of the test code. Now you can easily read the test code as you can see the input set right in front of you. Thus you can effortlessly create different input set from one basic prototype.&lt;/p&gt;&lt;p&gt;The interesting part of this section is the test of latest_post of user model. Here as you can see the association method ‘posts’ is overridden with expected post list. Now you can mock this this methods as this is provided by the framework itself. So no need to test it. But by mocking this you actually increased the readability of the test code and avoided database call.&lt;/p&gt;&lt;h4&gt;How shoulda helped&lt;/h4&gt;&lt;p&gt;The &lt;a href="http://thoughtbot.com/projects/shoulda"&gt;Shoulda&lt;/a&gt; gem makes it easy to write elegant, understandable, and maintainable Ruby tests. &lt;a href="http://thoughtbot.com/projects/shoulda"&gt;Shoulda&lt;/a&gt; consists of test macros, assertions, and helpers added on to the Test::Unit framework.&lt;/p&gt;&lt;p&gt;With &lt;a href="http://thoughtbot.com/projects/shoulda"&gt;shoulda&lt;/a&gt; we defined a context 'Default posts' and initialized it. We can test codes related to posts with in the context. As the context is setup with the minimum and sufficient information of input set needed for the context, the test code becomes very simple and easy to read and maintain.&lt;/p&gt;&lt;p&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;Resources&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://thoughtbot.com/projects/factory_girl"&gt;http://thoughtbot.com/projects/factory_girl&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://thoughtbot.com/projects/shoulda"&gt;http://thoughtbot.com/projects/shoulda&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-8851773272707798220?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/8851773272707798220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=8851773272707798220' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8851773272707798220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8851773272707798220'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/05/testing-model-in-rails.html' title='Testing model in rails'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-475791733360511074</id><published>2009-04-30T11:10:00.009+06:00</published><updated>2009-05-13T10:01:52.067+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='ec2'/><category scheme='http://www.blogger.com/atom/ns#' term='Amazon'/><title type='text'>Create Image from existing instance and reuse to create a new instance</title><content type='html'>&lt;p&gt;Often we need to create one production instance and another test instance for testing. Environment is similar for both instances. So if you are using Amazon ec2 then you can configure one instance and then create an image from that instance to reuse it to create another instance just like the first one.&lt;/p&gt;  &lt;h5&gt;Create volume from your instance&lt;/h5&gt;  &lt;p&gt;Copy pk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.pem and cert-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.pem file into /mnt folder in your instance.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;b&gt;Note:&lt;/b&gt; You can download these files from your amazon account.&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;  &lt;p&gt;/mnt is not included in the image so your certification files will be secured and not stored in the image.&lt;/p&gt;  &lt;p&gt;login to your instance and run in command line,&lt;/p&gt;  &lt;pre class="brush: bash; toolbar: false;"&gt;ec2-bundle-vol -d /mnt -k /mnt/pk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.pem -c /mnt/cert-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.pem -u xxxxxxxxxxxx -r i386 -s 1536&lt;/pre&gt;&lt;h5&gt;Here,&lt;/h5&gt;&lt;pre class="brush: plain; toolbar: false;"&gt;–d =&amp;gt; is the directory where the images will be generated
-k =&amp;gt; privatekey PATH
-c =&amp;gt; cert PATH
-u =&amp;gt; your AWS account ID as your username (not your AWS Access Key ID)
-r =&amp;gt; Specify target architecture. [i386, x86_64]
-s =&amp;gt; The size, in MB (1024 * 1024 bytes), of the image file to create. The maximum size is 10240 MB&lt;/pre&gt;&lt;h5&gt;upload bundle into your s3 bucket&lt;/h5&gt;&lt;p&gt;The&lt;span&gt;&lt;span&gt;n run&lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;code&gt;,&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;ec2-upload-bundle -b 'your-s3-bucket' -m /mnt/image.manifest.xml -a 'aws-access-key-id' -s 'aws-secret-access-key' &lt;/pre&gt;&lt;h5&gt;Register image&lt;/h5&gt;&lt;p&gt;run&lt;/p&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;ec2-register 'your-s3-bucket'/image.manifest.xml&lt;/pre&gt;&lt;p&gt;You should see some thing like this in the screen.&lt;/p&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;IMAGE   ami-xxxxxxxx&lt;/pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You might not get this command from instance. For this you will need ec2 api tool in you instance or in your local machine.&lt;/p&gt;&lt;p&gt;You can download it from &lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;h5&gt;Running Instances from your newly created image&lt;/h5&gt;&lt;p&gt;run&lt;/p&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;ec2-run-instances ami-xxxxxxxx&lt;/pre&gt;&lt;p&gt;You should see some thing like this in the screen.&lt;/p&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;RESERVATION     r-632db90a      106811649921    default
INSTANCE        i-xxxxxxxx      ami-xxxxxxxx                    pending
0               m1.small        2009-04-30T05:26:38+0000        us-east-1c&lt;/pre&gt;&lt;h4&gt;resources&lt;/h4&gt;&lt;p&gt;&lt;a href="http://docs.amazonwebservices.com/AmazonEC2/gsg/2006-06-26/creating-an-image.html"&gt;http://docs.amazonwebservices.com/AmazonEC2/gsg/2006-06-26/creating-an-image.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351"&gt;http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://wiki.apache.org/hadoop/AmazonEC2"&gt;http://wiki.apache.org/hadoop/AmazonEC2&lt;/a&gt;[For publishing Image as public]&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-475791733360511074?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/475791733360511074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=475791733360511074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/475791733360511074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/475791733360511074'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/create-image-from-existing-instance-and.html' title='Create Image from existing instance and reuse to create a new instance'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-4817417433956790487</id><published>2009-04-27T15:59:00.006+06:00</published><updated>2009-05-02T09:23:54.772+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Using webrat for integration testing</title><content type='html'>&lt;h4&gt;What is webrat&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://github.com/brynary/webrat/tree/master" target="_blank"&gt;Webrat&lt;/a&gt; lets you quickly write expressive and robust acceptance tests for a rails application.&lt;/p&gt;  &lt;h4&gt;How Webrat is different from default rails integration test&lt;/h4&gt;  &lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Rails default integration testing is nothing more than a series of functional tests. But in webrat you can actually do actions in pages. Here is a scenario for login.&lt;/p&gt;  &lt;pre class="brush: ruby; toolbar: false;"&gt;visit('/')
fill_in('email', :with =&amp;gt; user.email)
fill_in('password', :with =&amp;gt; '1234')
click_button('login')&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; With webrat you can test user experience by filling in the text boxes, clicking the buttons etc. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Use webrat API for Browser Simulator and real Selenium tests using &lt;a href="http://gitrdoc.com/classes/Webrat/Selenium.html"&gt;Webrat::Selenium&lt;/a&gt; when necessary (eg. for testing AJAX interactions).&lt;/p&gt;&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Supports popular test frameworks: &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt;, &lt;a href="http://wiki.github.com/aslakhellesoy/cucumber/ruby-on-rails"&gt;Cucumber&lt;/a&gt;, Test::Unit and &lt;a href="http://thoughtbot.com/projects/shoulda/"&gt;Shoulda&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Installing webrat&lt;/h4&gt;&lt;pre class="brush: bash; toolbar: false;"&gt;gem install nokogiri
gem install webrat&lt;/pre&gt;&lt;p&gt;In test_helper.rb add,&lt;/p&gt;&lt;pre class="brush: ruby; toolbar: false;"&gt;require "webrat"

Webrat.configure do |config|
 config.mode = :rails
end&lt;/pre&gt;&lt;p&gt;For more information please visit &lt;a href="http://github.com/brynary/webrat/tree/master"&gt;http://github.com/brynary/webrat/tree/master&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Some Tips&lt;/h4&gt;&lt;p&gt;You can check something like, if your desired dropdown select option is currently selected or not using assert_select.&lt;/p&gt;&lt;p&gt;Let me show you the expected html to test&lt;/p&gt;&lt;pre class="brush: xml; toolbar: false;"&gt;&amp;lt;select name="user[user_type_id]" id="user_user_type_id"&amp;gt;
 &amp;lt;option selected="selected" value="1"&amp;gt;Shipper&amp;lt;/option&amp;gt;
 &amp;lt;option value="2"&amp;gt;Transporter&amp;lt;/option&amp;gt;
&amp;lt;/select&amp;gt;&lt;/pre&gt;&lt;p&gt;Here we want to test of Shipper is selected or not.&lt;/p&gt;&lt;p&gt;So the test code can be&lt;/p&gt;&lt;pre class="brush: ruby; toolbar: false;"&gt;test 'signup form with shipper' do
 visit('/')
 click_link('Signup as Shipper')
 assert_selected_option('user_user_type_id', 'Shipper')
end

def assert_selected_option(select_id, selected_text)
 assert_select("##{select_id} option[selected=selected]", selected_text)
end&lt;/pre&gt;&lt;p&gt;This is how you can test contents of html.&lt;/p&gt;&lt;h4&gt;Resources&lt;/h4&gt;&lt;p&gt;&lt;a href="http://github.com/brynary/webrat/tree/master"&gt;http://github.com/brynary/webrat/tree/master&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.slideshare.net/brynary/webrat-rails-acceptance-testing-evolved"&gt;http://www.slideshare.net/brynary/webrat-rails-acceptance-testing-evolved&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://cheat.errtheblog.com/s/webrat/"&gt;http://cheat.errtheblog.com/s/webrat/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-4817417433956790487?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/4817417433956790487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=4817417433956790487' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4817417433956790487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4817417433956790487'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/using-webrat-for-integration-testing.html' title='Using webrat for integration testing'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-2792855222520671538</id><published>2009-04-26T11:53:00.002+06:00</published><updated>2009-04-26T17:51:45.126+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Rails route sequence</title><content type='html'>&lt;p&gt;For a large RESTful rails project routes can become very complicated and a single controller can be accessed under different resources.&lt;/p&gt;  &lt;p&gt;In rails 2.3.2 route sequence is important. Let me give a scenario,&lt;/p&gt;  &lt;pre class="brush: ruby; toolbar: false;"&gt;map.resources :shippers, :shallow =&amp;gt; true do |shipper|
 shipper.resources :jobs, :member =&amp;gt; {:publish =&amp;gt; :put} do |job|
 end
end

map.resources :jobs, :collection =&amp;gt; {:open_jobs =&amp;gt; :get}&lt;/pre&gt;&lt;p&gt;This will generate routes as follows(by running rake routes) &lt;/p&gt;&lt;pre class="brush: plain; toolbar: false;"&gt;job             GET    /jobs/:id(.:format)          {:action=&amp;gt;"show", :controller=&amp;gt;"jobs"}
open_jobs_jobs  GET    /jobs/open_jobs(.:format)    {:action=&amp;gt;"open_jobs", :controller=&amp;gt;"jobs"}&lt;/pre&gt;&lt;p&gt;As in route.rb file /job/:id route path is defined first, when you will hit /jobs/open_jobs you will be mapped to {:action=&amp;gt;"show", :controller=&amp;gt;"jobs",:id=&amp;gt;"open_jobs"}&lt;/p&gt;&lt;p&gt;Then when I moved the open_job route definition up before the job resource under shipper, and it worked. &lt;/p&gt;&lt;p&gt;And now /jobs/open_jobs was mapped to {:action=&amp;gt;"open_jobs", :controller=&amp;gt;"jobs"}. So the resource definition is now like,&lt;/p&gt;&lt;pre class="brush: ruby; toolbar: false;"&gt;map.resources :jobs, :collection =&amp;gt; {:open_jobs =&amp;gt; :get}

map.resources :shippers, :shallow =&amp;gt; true do |shipper|
 shipper.resources :jobs, :member =&amp;gt; {:publish =&amp;gt; :put} do |job|
 end
end&lt;/pre&gt;&lt;p&gt;Reordering the sequence resolved that routing issue.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-2792855222520671538?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/2792855222520671538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=2792855222520671538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2792855222520671538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2792855222520671538'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/rails-route-sequence.html' title='Rails route sequence'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-5005491773517763392</id><published>2009-04-24T21:14:00.003+06:00</published><updated>2009-06-19T09:52:52.938+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Use Migration Helpers to ease your migration script</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;One of the purpose of rails migration script was to wrap SQL with simple ruby code. But still we need some SQL for creating foreign key or inserting some default data or updating some existing data. There is a rails plugin to solve this problem.&lt;b&gt;&lt;a href='http://github.com/patientslikeme/migration_helpers/tree/master'&gt;migration_helpers&lt;/a&gt; &lt;/b&gt;provides some basic helpers for writing migration scripts.&lt;/p&gt;  &lt;p&gt;It wraps&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Add/remove foreign key &lt;/li&gt;    &lt;li&gt;Insert statements &lt;/li&gt;    &lt;li&gt;update statements &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Here is a sample migration that uses insert and update statement.&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;class CreatePosts &amp;lt; ActiveRecord::Migration
    def self.up
      create_table :posts do |t|
        t.string :title
        t.text :body
        t.boolean :published
    
        t.timestamps
      end
    
      insert_row('posts', :title =&amp;gt; 'Dummy Title', :body =&amp;gt; 'A sample post', :published =&amp;gt; false)
      update_row('posts', :set =&amp;gt; { :published =&amp;gt; true }, :where =&amp;gt; { :title =&amp;gt; 'Dummy Title' })
    end
    
    def self.down
      drop_table :posts
    end
end&lt;/pre&gt;And here is a sample migration that uses foreign key reference.&lt;pre class='brush: ruby;'&gt;class CreateComments &amp;lt; ActiveRecord::Migration&amp;lt;br /&amp;gt;    def self.up&amp;lt;br /&amp;gt;      create_table :comments do |t|&amp;lt;br /&amp;gt;        t.text :body&amp;lt;br /&amp;gt;        t.boolean :published&amp;lt;br /&amp;gt;        t.references :post&amp;lt;br /&amp;gt;    &amp;lt;br /&amp;gt;        t.timestamps&amp;lt;br /&amp;gt;      end&amp;lt;br /&amp;gt;    &amp;lt;br /&amp;gt;      add_foreign_key('comments', 'post_id', 'posts')&amp;lt;br /&amp;gt;    end&amp;lt;br /&amp;gt;    &amp;lt;br /&amp;gt;    def self.down&amp;lt;br /&amp;gt;      remove_foreign_key('comments', 'posts')&amp;lt;br /&amp;gt;      drop_table :comments&amp;lt;br /&amp;gt;    end&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;h4&gt;Caution:&lt;/h4&gt;&lt;p&gt;This is really a nice plugin but I needed to modify some code to work remove_foreign_key.&lt;/p&gt;&lt;p&gt;In plugins/migration_helpers/lib/migration_helpers_tasks.rb file replace the remove_foreign_key with the following code&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;def remove_foreign_key(table, target_table, constraint_name="#{table.to_s}_#{target_table.to_s}_fkey")&amp;lt;br /&amp;gt;    execute "ALTER TABLE #{table.to_s} DROP FOREIGN KEY #{constraint_name};"&amp;lt;br /&amp;gt;    execute "ALTER TABLE #{table.to_s} DROP KEY #{constraint_name};"&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;h5&gt;Reference:&lt;/h5&gt;&lt;p&gt;&lt;a href='http://github.com/patientslikeme/migration_helpers/tree/master'&gt;http://github.com/patientslikeme/migration_helpers/tree/master&lt;/a&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-5005491773517763392?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/5005491773517763392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=5005491773517763392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/5005491773517763392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/5005491773517763392'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/use-migration-helpers-to-ease-your.html' title='Use Migration Helpers to ease your migration script'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-3938776903509547171</id><published>2009-04-23T12:54:00.006+06:00</published><updated>2009-06-19T10:01:42.281+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Transaction in rails 2.3.2</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;In rails when we want some series of tasks to be atomic we use &lt;a target='_blank' href='http://ryandaigle.com/articles/2007/3/20/what-s-new-in-edge-rails-object-transactions-are-out'&gt;transaction&lt;/a&gt;. But how should we write our code to support transaction?&lt;/p&gt;  &lt;p&gt;Let me explain how transaction in rails works. If any code inside a transaction raises an exception &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;the transaction block rescues it &lt;/li&gt;    &lt;li&gt;rolls back the database and &lt;/li&gt;    &lt;li&gt;re throws the exception &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So we need to make sure that statements that are not complete, raise exception. Here are some scenarios with explanation.&lt;/p&gt;  &lt;p&gt;For all the scenarios the Comment model is like,&lt;/p&gt;  &lt;pre class='brush: ruby;'&gt;class Comment &amp;lt; ActiveRecord::Base
  belongs_to :post
  validates_presence_of :body
end&lt;/pre&gt;&lt;p&gt;As model.collection &amp;lt;&amp;lt; child_model does not raises exception the post is saved, as the transaction is unaware of the data save failure.&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;test 'transaction should not rollback transaction with collection create method' do&amp;lt;br /&amp;gt;  is_comment_saved = false&amp;lt;br /&amp;gt;  Post.transaction do&amp;lt;br /&amp;gt;    post = Post.new({:title=&amp;gt; 'Test title', :body =&amp;gt; 'A sample post', :published =&amp;gt; true})&amp;lt;br /&amp;gt;    post.save!&amp;lt;br /&amp;gt;    is_comment_saved = post.comments &amp;lt;&amp;lt; Comment.new({:published =&amp;gt; true})&amp;lt;br /&amp;gt;    #Comment with out body should be not saved for validation&amp;lt;br /&amp;gt;    #but this does not raise exception so the transaction is not rolled back&amp;lt;br /&amp;gt;    #I know that rails convention is that you first assign the comment and then save post&amp;lt;br /&amp;gt;    #But there might be situation when you might want to save model which is unrelated to post in the same transaction&amp;lt;br /&amp;gt;  end&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  assert_equal(1, Post.count)&amp;lt;br /&amp;gt;  assert_equal(0, Comment.count)&amp;lt;br /&amp;gt;  assert_equal(false, is_comment_saved)&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;p&gt;To support transaction we need to write some thing like this,&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;test 'transaction should rollback transaction with throwing exception manually' do&amp;lt;br /&amp;gt;  is_comment_saved = false&amp;lt;br /&amp;gt;  begin&amp;lt;br /&amp;gt;    Post.transaction do&amp;lt;br /&amp;gt;      post = Post.new({:title=&amp;gt; 'Test title', :body =&amp;gt; 'A sample post', :published =&amp;gt; true})&amp;lt;br /&amp;gt;      post.save!&amp;lt;br /&amp;gt;      #Comment with out body should be not saved for validation&amp;lt;br /&amp;gt;      raise Exception unless post.comments &amp;lt;&amp;lt; Comment.new({:published =&amp;gt; true})&amp;lt;br /&amp;gt;    end&amp;lt;br /&amp;gt;  rescue Exception&amp;lt;br /&amp;gt;  end&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  assert_equal(0, Post.count)&amp;lt;br /&amp;gt;  assert_equal(0, Comment.count)&amp;lt;br /&amp;gt;  assert_equal(false, is_comment_saved)&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;p&gt;model.collection &amp;lt;&amp;lt; returns false the operation fails. So raising an exception while it returns false causes the transaction to rollback.&lt;/p&gt;&lt;p&gt;Let me give you a scenario with nested transaction.&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;test 'default Nested transaction should rollback with raising Exception' do&amp;lt;br /&amp;gt;  begin&amp;lt;br /&amp;gt;    Post.transaction do&amp;lt;br /&amp;gt;      post = Post.new({:title=&amp;gt; 'Test title', :body =&amp;gt; 'A sample post', :published =&amp;gt; true})&amp;lt;br /&amp;gt;      post.save!&amp;lt;br /&amp;gt;      Comment.transaction(:requires_new =&amp;gt; true) do&amp;lt;br /&amp;gt;        post.comments.create({:body =&amp;gt; 'A sample comment', :published =&amp;gt; true})&amp;lt;br /&amp;gt;        raise Exception&amp;lt;br /&amp;gt;      end&amp;lt;br /&amp;gt;    end&amp;lt;br /&amp;gt;  rescue Exception =&amp;gt; error&amp;lt;br /&amp;gt;  end&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  assert_equal(0, Post.count)&amp;lt;br /&amp;gt;  assert_equal(0, Comment.count)&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Note:&lt;/u&gt; For nested transaction in rails 2.3.2 by default any transaction inherits the transaction of it’s parent transaction. To make a new child transaction you need to pass “:requires_new =&amp;gt; true” as the parameter of transaction method.&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Identical to single transaction nested transaction behaves same if you throw an exception. So if you really mean to use a child transaction, you will need to handle exception inside or around the child transaction.&lt;/p&gt;&lt;p&gt;The above example  behaves same even if we do not use “:requires_new =&amp;gt; true” for child transaction. now If you want to break the child transaction and not to interfere the parent transaction, you can use “ActiveRecord::Rollback”.&lt;/p&gt;&lt;p&gt;Transaction relays all the exception except ActiveRecord::Rollback. If you raise ActiveRecord::Rollback then the steps are&lt;/p&gt;&lt;ol&gt;  &lt;li&gt;the transaction block rescues it&lt;/li&gt;  &lt;li&gt;rolls back the database and&lt;/li&gt;  &lt;li&gt;&lt;span style='color: rgb(255, 0, 0);'&gt;DOES NOT&lt;/span&gt; re throw the exception&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Here is an example,&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;test 'nested transaction should not rollback parent transaction that throws ActiveRecord Rollback in child transaction' do&amp;lt;br /&amp;gt;  begin&amp;lt;br /&amp;gt;    Post.transaction do&amp;lt;br /&amp;gt;      post = Post.new({:title=&amp;gt; 'Test title', :body =&amp;gt; 'A sample post', :published =&amp;gt; true})&amp;lt;br /&amp;gt;      post.save!&amp;lt;br /&amp;gt;      Comment.transaction(:requires_new =&amp;gt; true) do&amp;lt;br /&amp;gt;        comment = Comment.new({:body =&amp;gt; 'Test', :published =&amp;gt; true, :post_id =&amp;gt; post.id})&amp;lt;br /&amp;gt;        comment.save!&amp;lt;br /&amp;gt;        raise ActiveRecord::Rollback&amp;lt;br /&amp;gt;      end&amp;lt;br /&amp;gt;    end&amp;lt;br /&amp;gt;  rescue Exception&amp;lt;br /&amp;gt;  end&amp;lt;br /&amp;gt;  assert_equal(1, Post.count)&amp;lt;br /&amp;gt;  assert_equal(0, Comment.count)&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;p&gt;In rails 2.3.2 ActiveRecord::Rollback does not work for child transaction that is not defined as :requires_new =&amp;gt; true.&lt;/p&gt;&lt;p&gt;Here is another scenario for that test,&lt;/p&gt;&lt;pre class='brush: ruby;'&gt;test 'default nested transaction should not rollback even child trasnsaction that throws exception in child transaction' do&amp;lt;br /&amp;gt;  Post.transaction do&amp;lt;br /&amp;gt;    post = Post.new({:title=&amp;gt; 'Test title', :body =&amp;gt; 'A sample post', :published =&amp;gt; true})&amp;lt;br /&amp;gt;    post.save!&amp;lt;br /&amp;gt;    Comment.transaction do&amp;lt;br /&amp;gt;      comment = Comment.new({:body =&amp;gt; 'Test', :published =&amp;gt; true, :post_id =&amp;gt; post.id})&amp;lt;br /&amp;gt;      comment.save!&amp;lt;br /&amp;gt;      raise ActiveRecord::Rollback&amp;lt;br /&amp;gt;    end&amp;lt;br /&amp;gt;  end&amp;lt;br /&amp;gt;  assert_equal(1, Post.count)&amp;lt;br /&amp;gt;  #Here comment is saved too&amp;lt;br /&amp;gt;  assert_equal(1, Comment.count)&amp;lt;br /&amp;gt;end&lt;/pre&gt;&lt;p&gt;As you can see raising ActiveRecord::Rollback does not impact the result.&lt;/p&gt;&lt;p&gt;These are some of the scenario explained, which should help you to choose appropriate way to use transaction for your application.&lt;/p&gt;&lt;p&gt;You can download the test project from &lt;a href='http://demo.ashrafuzzaman.com/rails/RailsTransactionTest.zip'&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-3938776903509547171?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/3938776903509547171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=3938776903509547171' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/3938776903509547171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/3938776903509547171'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/proper-use-of-transaction-in-rails.html' title='Transaction in rails 2.3.2'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-1506229284858926813</id><published>2009-04-23T09:07:00.013+06:00</published><updated>2009-04-23T15:51:10.375+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Add custom rake task in your rails project</title><content type='html'>&lt;p&gt;It is very easy to create a custom rake task in rails. We can often use this feature to ease our daily work. Recently I needed to run a cron job for a rails project, which is the perfect place for a custom rake task. You can follow these process to create a task.&lt;/p&gt;  &lt;p&gt;1. Create a rake file as your_tasks.rake and put it in project_path\lib\tasks\&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;rails detects task from project_path\lib\tasks\&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;2. A sample rake task&lt;/p&gt;  &lt;pre class="brush: ruby"&gt;
task :start do
  #do some magic and start the cron
end
task :stop do
  #do some more magic and stop IT
end&lt;/pre&gt;&lt;p&gt;3. Now run in command prompt from the project folder as&lt;/p&gt;&lt;pre class="brush: bash"&gt;rake start&lt;/pre&gt;&lt;p&gt;To make your tasks more meaningful you might want to try giving namespaces and a little description which explains the task a bit.&lt;/p&gt;&lt;p&gt;Here the simple modification you need&lt;/p&gt;&lt;p&gt;Rake task&lt;/p&gt;&lt;pre class="brush: ruby; highlight: [1, 2, 6, 10]"&gt;
namespace :cron do
  desc "Starts cron job"
  task :start do
    #do some magic and start the cron
  end
  desc "Stops cron job"
  task :stop do
    #do some more magic and stop IT
  end
end&lt;/pre&gt;&lt;p&gt;Calling tasks&lt;/p&gt;&lt;pre class="brush: bash"&gt;rake cron:start&lt;/pre&gt;&lt;p&gt;Rake gives us the flexibility of defining dependent tasks so that the dependent tasks can be executed first.&lt;/p&gt;&lt;p&gt;Often we may need our rails environment to load before we do any thing. You can do it by&lt;/p&gt;&lt;pre class="brush: ruby; highlight: [3, 7]"&gt;
namespace :cron do
  desc "Starts cron job"
  task(:start =&amp;gt; :environment)do
    #do some magic and start the cron
  end
  desc "Stops cron job"
  task(:stop =&amp;gt; :environment)do
    #do some more magic and stop IT
  end
end&lt;/pre&gt;&lt;p&gt;Now when you will run the task, you will find that your environment is now loaded.&lt;/p&gt;&lt;p&gt;Resource:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial"&gt;http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://rake.rubyforge.org/"&gt;http://rake.rubyforge.org/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://martinfowler.com/articles/rake.html"&gt; http://martinfowler.com/articles/rake.html &lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-1506229284858926813?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/1506229284858926813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=1506229284858926813' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/1506229284858926813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/1506229284858926813'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/add-custom-rake-task-in-your-rails.html' title='Add custom rake task in your rails project'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-8306758337657998812</id><published>2009-04-20T20:32:00.004+06:00</published><updated>2009-04-21T08:33:48.216+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Using Gem Dependencies to ease gem installation process</title><content type='html'>&lt;p&gt;A rails project eventually gets involved with a lot of gems and plugins. Plugins are kept in the project(in vendor folder). But gems are installed in the system. It is difficult to synchronize gem if a project is developed by more than one developer. And eventually you will need to install those gems in your deployment server.&lt;/p&gt;  &lt;p&gt;Rails 2 has given an elegant solution for that problem. In environment.rb file use following:&lt;/p&gt;  &lt;pre class="brush:ruby"&gt;Rails::Initializer.run do |config|

# Require the latest version of haml
config.gem "haml"

# Require a specific version of chronic
config.gem "chronic", :version =&amp;gt; '0.2.3'

# Require a gem from a non-standard repo
config.gem "hpricot", :source =&amp;gt; "http://code.whytheluckystiff.net"

# Require a gem that needs to require a file different than the gem's name
# I.e. if you normally load the gem with require 'aws/s3' instead of
# require 'aws-s3' then you would need to specify the :lib option
config.gem "aws-s3", :lib =&amp;gt; "aws/s3"
end&lt;/pre&gt;&lt;p&gt;There’s now a rake task that will install all the referenced config.gems on your target system:&lt;/p&gt;&lt;pre class="brush:bash"&gt;rake gems:install&lt;/pre&gt;&lt;p&gt;See list of gems, your project depends on&lt;/p&gt;&lt;pre class="brush:bash"&gt;rake gems&lt;/pre&gt;&lt;p&gt;Resource:&lt;/p&gt;&lt;p&gt;&lt;a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies"&gt;http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://rubygems.org/read/chapter/10#page29"&gt;http://rubygems.org/read/chapter/10#page29&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-8306758337657998812?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/8306758337657998812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=8306758337657998812' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8306758337657998812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8306758337657998812'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/using-gem-dependencies-to-ease-gem.html' title='Using Gem Dependencies to ease gem installation process'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-7348465575279407291</id><published>2009-04-13T10:05:00.003+06:00</published><updated>2009-04-14T19:23:28.029+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>DateTime with zone support in rails fixture</title><content type='html'>&lt;p&gt;To get time with zone support we usually call, Time.now.utc&lt;/p&gt;&lt;p&gt;But if we use Time.now.utc in fixture like,&lt;/p&gt;&lt;pre class="brush: ruby"&gt;fixture1:
deadline: &amp;lt;%= Time.now.utc %&amp;gt;&lt;/pre&gt;&lt;p&gt;It gives an error:&lt;/p&gt;&lt;blockquote&gt;  &lt;p&gt;ActiveRecord::StatementInvalid: Mysql::Error: Incorrect datetime value: 'Sun Apr 12 11:40:05 UTC 2009' for column 'deadline' at row 1: INSERT INTO job_assignments (job_id, updated_at, id, deadline, transporter_fee, transporter_id, created_at, state) VALUES (245383586, '2009-04-12 09:40:07', 809788707, 'Sun Apr 12 11:40:05 UTC 2009', 75, 468814034, '2009-04-12 09:40:07', 'assigned')&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Because fixtures calls a default to_s function for each fields to create the insert script. Fixtures does not save records through Models. Time.now.utc.to_s generates a string which is not in the format to save date time in mysql. To generate such format we need to call Time.now.utc.to_s(:db). So the fixture turned out like,&lt;/p&gt;&lt;pre class="brush: ruby"&gt;fixture1:
deadline: &amp;lt;%= Time.now.utc.to_s(:db) %&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-7348465575279407291?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/7348465575279407291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=7348465575279407291' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/7348465575279407291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/7348465575279407291'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/04/datetime-with-zone-support-in-rails.html' title='DateTime with zone support in rails fixture'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-4399816571658032493</id><published>2009-02-01T21:01:00.030+06:00</published><updated>2009-04-27T23:24:56.385+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Png Corner is the solution of rounded/styled corners which is browser compatible</title><content type='html'>&lt;p&gt;I was searching for an easy and simple implementation of smooth rounded corner that is browser compatible. If you want smooth corners you will need &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;png&lt;/span&gt;&lt;/span&gt; images and Internet Explorer 6 has issues with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;png&lt;/span&gt;&lt;/span&gt; alpha transparency. Then I came with a project &lt;a href="http://code.google.com/p/pngcorner/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;pngcorner&lt;/span&gt;&lt;/span&gt;&lt;/a&gt; . This is very easy to use and very small in size(less than 4 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;kb&lt;/span&gt;&lt;/span&gt; ). You can download the demo from &lt;a href="http://code.google.com/p/pngcorner/downloads/list"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;For &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;png&lt;/span&gt;&lt;/span&gt; transparency I used &lt;a href="http://unitinteractive.com/labs/unitpngfix.php"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;unitpngfix&lt;/span&gt;&lt;/span&gt;&lt;/a&gt; , a very small(less than 1 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;kb&lt;/span&gt;&lt;/span&gt; ) and yet very effective javascript library. And used a table structure rounded corner template. For detail please visit the &lt;a href="http://code.google.com/p/pngcorner/"&gt;project page&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Here is a &lt;a href="http://demo.ashrafuzzaman.com/css/png%20corner/Rounded%20Corner%20Demo.html"&gt;demo&lt;/a&gt; and here is the &lt;a href="http://demo.ashrafuzzaman.com/css/png%20corner/Rounded%20Corner%20Demo%20with%20jQuery.html"&gt;demo&lt;/a&gt; with jquery plugin.&lt;/p&gt; &lt;h4&gt;Why use &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;png&lt;/span&gt;&lt;/span&gt; corners&lt;/h4&gt; &lt;ol&gt; &lt;li&gt;It is browser compatible(works in IE 6/7, FireFox 3, Opera 9, Chrome 1.x)  &lt;/li&gt;&lt;li&gt;It's small(less than 4 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;kb&lt;/span&gt;&lt;/span&gt; )  &lt;/li&gt;&lt;li&gt;Easy to use(Just follow 3 easy steps)  &lt;/li&gt;&lt;li&gt;Can use &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;png&lt;/span&gt;&lt;/span&gt; transparency feature so that you can create your own styled box.  &lt;/li&gt;&lt;li&gt;Same behavior across browsers  &lt;/li&gt;&lt;li&gt;Size of your content is totally flexible  &lt;/li&gt;&lt;li&gt;You can change images from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;css&lt;/span&gt;&lt;/span&gt; &lt;/li&gt;&lt;/ol&gt; &lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;Why special&lt;/span&gt;&lt;/div&gt; &lt;div&gt;There are a lot of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_11"&gt;implementation&lt;/span&gt; on rounded corner. And there are simpler implementation.&lt;/div&gt; &lt;div&gt;But if you need smooth(using &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;png&lt;/span&gt; images), transparent(that works even in IE6), &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_13"&gt;browser&lt;/span&gt; &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_14"&gt;compatible&lt;/span&gt;, small(less than 4&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;kb&lt;/span&gt;), with flexible content dimension(content can have any dimension) you should use &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;pngcorners&lt;/span&gt;.&lt;/div&gt;
&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;Places to use&lt;/span&gt;&lt;/div&gt; &lt;div&gt; &lt;ol&gt; &lt;li&gt;Use to create smooth rounded corner content with shades  &lt;/li&gt;&lt;li&gt;Use to create buttons with shades(as the size is expandable you can have small buttons as well as long ones) &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt; &lt;h4&gt;Limitations&lt;/h4&gt; &lt;ol&gt; &lt;li&gt;It uses table for the structure of rounded corner. So your rounded corner is not as flexible as div layout (It is a small sacrifice for IE 6 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;png&lt;/span&gt;&lt;/span&gt; transparency)  &lt;/li&gt;&lt;li&gt;The images at left, right, top and bottom will be scaled not repeated. As Microsoft.Alpha filter do not support repeating. &lt;/li&gt;&lt;/ol&gt; &lt;h4&gt;Usage&lt;/h4&gt; &lt;p&gt;1. Add &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;png&lt;/span&gt;&lt;/span&gt; _corner. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;css&lt;/span&gt;&lt;/span&gt; in page&lt;/p&gt; &lt;p&gt;2. Add html structure for rounded corner, which looks like this,&lt;/p&gt;  &lt;pre class="brush: html"&gt;&amp;lt;table class="rounded_corner" border="0" cellpadding="0" cellspacing="0"&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;td class="top_left"/&amp;gt;&amp;lt;td class="top"/&amp;gt;&amp;lt;td class="top_right"/&amp;gt; &amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;td class="left"/&amp;gt;
    &amp;lt;td class="content"&amp;gt;The content goes here :)&amp;lt;/td&amp;gt;
    &amp;lt;td class="right"/&amp;gt;
  &amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;td class="bottom_left"/&amp;gt;&amp;lt;td class="bottom"/&amp;gt;&amp;lt;td class="bottom_right"/&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;&lt;/pre&gt;&lt;p&gt;3. Add &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;png&lt;/span&gt;&lt;/span&gt; hack &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;css&lt;/span&gt;&lt;/span&gt; in header as shown bellow so that the script is only added for Internet Explorer 6.&lt;/p&gt;&lt;p&gt;4. Add clear. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_70"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;gif&lt;/span&gt;&lt;/span&gt; in root_file/images&lt;/p&gt;&lt;p&gt;And you should be good to go :)&lt;/p&gt;&lt;p&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;jQuery&lt;/span&gt; Version&lt;/span&gt;&lt;/p&gt;&lt;p&gt;There is a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;jQuery&lt;/span&gt; version of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;png&lt;/span&gt; corners. For that you will have to follow all the steps and add another javascript file &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;pngcorners&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;js&lt;/span&gt;. But now the step 2 is now being simplified.&lt;/p&gt;&lt;p&gt;No need to remember all those tags and make your view complex. Just call,&lt;/p&gt;&lt;pre class="brush: js"&gt;$(".round_me").pngcorner();&lt;/pre&gt;&lt;p&gt;Where you are expecting for elements with round_me class name will become rounded corner :)&lt;/p&gt;&lt;p&gt;So it reduces tags and cleans the view a bit.&lt;/p&gt;&lt;p&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;&lt;span class="Apple-style-span" style="font-weight: normal"&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;Caution&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;When you load you content from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_71"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;ajax&lt;/span&gt;&lt;/span&gt; call or create your content dynamically after your page is loaded then you have to call the following javascript after you have done loading your content.&lt;/p&gt;&lt;pre class="brush: js"&gt;pngfix();&lt;/pre&gt;&lt;p&gt;I am still searching for a solution with lesser limitation and complexity. So any suggestion is welcome.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-4399816571658032493?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/4399816571658032493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=4399816571658032493' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4399816571658032493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/4399816571658032493'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/02/png-corner-is-solution-of-roundedstyled.html' title='Png Corner is the solution of rounded/styled corners which is browser compatible'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-6210296809118657144</id><published>2009-01-11T14:27:00.002+06:00</published><updated>2009-04-14T19:22:04.856+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><title type='text'>Test rails with Mocha</title><content type='html'>&lt;p&gt;Rails is a framework that came up with facilities for testing using fixtures. Testing using  fixture is a nice feature to have for a small project. But as the project grows some problems might be seen. Like,&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Difficult to manage fixture &lt;/li&gt;    &lt;li&gt;Takes long time to run the test &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Difficult to manage fixture:&lt;/h4&gt;  &lt;p&gt;As it becomes hard to manage fixtures, people tends to &lt;strong&gt;add&lt;/strong&gt; and do not intend to reuse existing, as that might break current test codes.&lt;/p&gt;  &lt;p&gt;So the number of the entry in fixtures increase day by day. Eventually it becomes unmanageable.&lt;/p&gt;  &lt;h4&gt;Takes long time to run the test:&lt;/h4&gt;  &lt;p&gt;As fixture driven testing takes a lot time to run the test. People don't feel comfortable to run test for a large project. Even running one test file sometime takes 2/3 minutes. We use &lt;a href="http://cruisecontrolrb.thoughtworks.com/" target="_blank"&gt;Continuous Integration(CI)&lt;/a&gt; to run test for the whole project in different server, while we do our regular tasks. But even that is not working out for us right now. Because, It takes about 30 minutes to test the whole project. CI looks up in repository and check for changes and if found any, it starts to build and run test. So If any code is checked in with in with in 30 minutes while the build is not completed, then that build goes into queue. And eventually we get the email notification from CI after 1/2 hours. Which is not satisfying the purpose of CI.&lt;/p&gt;  &lt;h4&gt;Solution:&lt;/h4&gt;  &lt;p&gt;I read about &lt;a href="http://mocha.rubyforge.org/" target="_blank"&gt;Mocha&lt;/a&gt; and really got interested. It is a solution to fixtures. You can use mock object to replace fixtures. At first I was confused about how should I mock my model objects. As it contains the business logic as well as the logic to save in database. &lt;a href="http://mocha.rubyforge.org/" target="_blank"&gt;Mocha&lt;/a&gt; gives you a solution as it gives facility to overwrite methods for an object without writing a real class. So you can mock save or find method of ActiveRecord and replace it with mock method with out creating a class. You can even mock a private method. Here is an &lt;a href="http://mocha.rubyforge.org/examples/misc.html" target="_blank"&gt;example&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-6210296809118657144?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/6210296809118657144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=6210296809118657144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6210296809118657144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6210296809118657144'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/01/test-rails-with-mocha.html' title='Test rails with Mocha'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-6563177398780376107</id><published>2009-01-07T18:41:00.002+06:00</published><updated>2009-04-14T19:08:13.317+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><title type='text'>Replacing Prototype with jQuery in Rails</title><content type='html'>&lt;p&gt;&lt;a href="http://jquery.com/" target="_blank"&gt;jQuery&lt;/a&gt; is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. &lt;/p&gt;  &lt;p&gt;For people who like to use &lt;a href="http://jquery.com/" target="_blank"&gt;jQuery&lt;/a&gt; in rails there is a  good news. There is a plugin &lt;a href="http://ennerchi.com/projects/jrails" target="_blank"&gt;jRails&lt;/a&gt;, which overwrites remote tags provided by rails and uses jQuery ajax call. You can find the project &lt;a href="http://code.google.com/p/ennerchi/" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ennerchi.com/projects/jrails" target="_blank"&gt;jRails&lt;/a&gt; covers all of the functionality in the built in Rails prototype_helper as well as some of the functionality in scriptaculous_helper. Current release includes support for basic AJAX calls (form_to_remote, link_to_remote), RJS, observers (observe_form, observe_field) as well as a limited set of functionality for draggables, droppables, sortables and visual effects.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Resources:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://jquery.com/" target="_blank"&gt;jQuery home page&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ennerchi.com/projects/jrails" target="_blank"&gt;jRails plugin&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/ennerchi/" target="_blank"&gt;jRails project page&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://justtalkaboutweb.com/2008/01/14/replace-prototype-with-jquery-on-rails/"&gt;http://justtalkaboutweb.com/2008/01/14/replace-prototype-with-jquery-on-rails/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-6563177398780376107?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/6563177398780376107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=6563177398780376107' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6563177398780376107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6563177398780376107'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/01/replacing-prototype-with-jquery-in.html' title='Replacing Prototype with jQuery in Rails'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-47553957000558472</id><published>2009-01-07T09:31:00.004+06:00</published><updated>2009-01-07T10:00:40.173+06:00</updated><title type='text'>Era of Multiprotocol Instant Messenger</title><content type='html'>Now a days people have at least 2 email accounts and most of the accounts are from different provider. When I am in my office I use gtalk for office account and yahoo messenger for my personal account. Open emails in gmail and yahoo. And might open facebook or any social networking sites. But now &lt;a href="http://www.digsby.com/"&gt;digsby&lt;/a&gt; has reduced much of these work. In one login to digsby I can login to messenger for gmail, yahoo or even facebook and more. See mail titles of various accounts and facebook feeds. And it is very intuitive and customizable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-47553957000558472?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/47553957000558472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=47553957000558472' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/47553957000558472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/47553957000558472'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2009/01/era-of-multiprotocol-instant-messenger.html' title='Era of Multiprotocol Instant Messenger'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-6032571512329143654</id><published>2008-11-25T15:18:00.001+06:00</published><updated>2009-01-15T12:10:42.739+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Amazon'/><title type='text'>Amazon Flexible Payments Service</title><content type='html'>&lt;h4&gt;Key features include&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;Send and receive money using credit card, bank account or Amazon Payments balance transfer as payment methods. &lt;/li&gt;    &lt;li&gt;Create &amp;#8220;Payment Instructions&amp;#8221; to define conditions and constraints desired for a given transaction, and programmatically obtain payment authorizations or &amp;#8220;tokens&amp;#8221; that represent these Payment Instructions from customers. &lt;/li&gt;    &lt;li&gt;Execute one-time, multiple, or recurring payments on behalf of customers. &lt;/li&gt;    &lt;li&gt;Aggregate micro-transactions into a single larger transaction using Prepaid and Postpaid capabilities. &lt;/li&gt;    &lt;li&gt;Integrate Amazon FPS into your website in minutes with &lt;a href="https://payments.amazon.com/sdui/sdui/business?sn=paynow/o" target="_blank"&gt;Amazon Simple Pay&lt;/a&gt;, a set of copy-and-paste HTML buttons. &lt;/li&gt;    &lt;li&gt;Build payment applications where you are neither the sender nor the recipient of funds. You can build marketplace applications that enable the movement of money between two third parties. Try &lt;a href="https://payments.amazon.com/sdui/sdui/business?sn=paynow/o" target="_blank"&gt;Amazon Simple Pay Marketplace&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;View account balances, transaction histories, and transaction details on the &lt;a href="https://payments.amazon.com/sdui/sdui/index.htm"&gt;Amazon Payments&lt;/a&gt; web site. &lt;/li&gt;    &lt;li&gt;Utilize the Amazon FPS sandbox to build and test applications without using real money or incurring any transaction charges. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;References&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://aws.amazon.com/fps/#legal"&gt;http://aws.amazon.com/fps/#legal&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://docs.amazonwebservices.com/AmazonFPS/2007-01-08/FPSDeveloperGuide/"&gt;http://docs.amazonwebservices.com/AmazonFPS/2007-01-08/FPSDeveloperGuide/&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;General Process&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Generate a caller token(Needed once for each application) &lt;/li&gt;    &lt;li&gt;Generate a recipient token &lt;/li&gt;    &lt;li&gt;Generate a co-branded UI url with caller and recipient token &lt;/li&gt;    &lt;li&gt;Redirect to Amazon with a generated co-branded UI url &lt;/li&gt;    &lt;li&gt;Amazon will redirect to your web site with a sender token &lt;/li&gt;    &lt;li&gt;Execute Payment using caller, recipient and sender token &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Sample Source Code and API can be found &lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=140"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Plugins&lt;/h4&gt;  &lt;p&gt;There are 2 plugins &lt;a href="http://github.com/mhodgson/amazon_fps_foo/tree/master"&gt;amazon_fps_foo&lt;/a&gt; and &lt;a href="http://github.com/tylerhunt/remit/tree/master"&gt;remit&lt;/a&gt;. I could not find much documentation for &lt;a href="http://github.com/mhodgson/amazon_fps_foo/tree/master"&gt;amazon_fps_foo&lt;/a&gt;.&lt;/p&gt;  &lt;h5&gt;Remit&lt;/h5&gt;  &lt;p&gt;&lt;a href="http://github.com/tylerhunt/remit/tree/master"&gt;Remit&lt;/a&gt; uses a REST implementation of Amazon Flexible Payments Service (FPS). &lt;/p&gt;  &lt;p&gt;There is an example for a &amp;quot;simple&amp;quot; implementation of a &amp;quot;marketplace&amp;quot; charge (one in which you are charging a client for a   &lt;br /&gt;product on behalf of another party): &lt;a href="http://gist.github.com/46941"&gt;http://gist.github.com/46941&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Testing&lt;/h4&gt;  &lt;p&gt;You can check your code with out flowing real money. &lt;a href="http://docs.amazonwebservices.com/AmazonFPS/2007-01-08/FPSGettingStartedGuide/gsSignUpSandbox.html"&gt;Sandbox&lt;/a&gt; is the test server for checking your code regarding FPS.&lt;/p&gt;  &lt;h4&gt;Developer Resources&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.railsinside.com/plugins/172-rails-and-amazon-libraries-and-plugins-for-ec2-s3-simpledb-sqs-fps-and-devpay-integration.html" target="_blank"&gt;Rails and Amazon: Libraries and Plugins for EC2, S3, SimpleDB, SQS, FPS and DevPay Integration&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="https://fps.amazonaws.com/doc/2007-01-08/AmazonFPS.wsdl"&gt;WSDL&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=125"&gt;Documentation&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=124"&gt;Release Notes&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=126"&gt;Amazon FPS Sample Code &amp;amp; Libraries&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=167"&gt;Amazon Simple Pay Code &amp;amp; Libraries&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=151"&gt;Articles &amp;amp; Tutorials&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/forum.jspa?forumID=35"&gt;Community Forum&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Additional Product Information&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://aws.amazon.com/fps/faqs/"&gt;FAQs&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="https://developer.payments-sandbox.amazon.com/landingpage/"&gt;Amazon FPS Sandbox&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="https://payments.amazon.com/sdui/sdui/index.htm"&gt;Amazon Payments Account Management web site&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=913"&gt;Amazon Simple Pay Integration Guide&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://aws.amazon.com/agreement"&gt;Amazon Web Services Customer Agreement&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="https://payments.amazon.com/sdui/sdui/about?acceptableuse"&gt;Amazon Payments Acceptable Use Policy&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://status.aws.amazon.com/"&gt;Service Health Dashboard&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-6032571512329143654?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/6032571512329143654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=6032571512329143654' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6032571512329143654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6032571512329143654'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2008/11/amazon-flexible-payments-service.html' title='Amazon Flexible Payments Service'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-6055484436842109240</id><published>2008-11-21T18:43:00.001+06:00</published><updated>2009-01-26T22:59:05.162+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Collection of some useful jquery plugins</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;Some of useful jquery plugins I found. I have tested these plugins in IE6 and FireFox.&lt;/p&gt;  &lt;h3&gt;Datagrids&lt;/h3&gt;  &lt;p&gt;&lt;a title="http://trirand.com/jqgrid/jqgrid.html" href="http://trirand.com/jqgrid/jqgrid.html"&gt;http://trirand.com/jqgrid/jqgrid.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://webplicity.net/flexigrid/" href="http://webplicity.net/flexigrid/"&gt;http://webplicity.net/flexigrid/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Animations&lt;/h3&gt;  &lt;p&gt;To animate your web page content flying from left and right &lt;a href="http://www.ezjquery.com/cgi-bin/webapp.rb?r=access#"&gt;Easy Slide&lt;/a&gt;&amp;#160;&lt;a href="http://www.ezjquery.com/pop.html#"&gt;demo&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You want to flip your content? There you &lt;a href="http://lab.smashup.it/flip/#"&gt;go&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Chain your animation. &lt;a href="http://www.decodeuri.com/jquery-fxqueues-plugin-20/"&gt;Home Page&lt;/a&gt;&amp;#160;&lt;a href="http://www.decodeuri.com/fxqueues2.0/2.0.2/example.html"&gt;demo&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.dummwiam.com/jTypeWriter" href="http://www.dummwiam.com/jTypeWriter"&gt;jTypeWriter&lt;/a&gt; gives a type writer effect with your text.&lt;/p&gt;  &lt;h3&gt;Effects&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://plugins.jquery.com/project/elementgradient"&gt;Gradient effect without images&lt;/a&gt;&amp;#160;&lt;a href="http://www.unitorganizer.com/javascript/gradients/index.html"&gt;demo&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html"&gt;Highlights&lt;/a&gt; text within the html&lt;/p&gt;  &lt;p&gt;Charts and bars can be drawn with &lt;a title="http://omnipotent.net/jquery.sparkline/" href="http://omnipotent.net/jquery.sparkline/"&gt;sparkline&lt;/a&gt; (need to test in ie)&lt;/p&gt;  &lt;p&gt;A gradient effect on &lt;a href="http://www.si-les-idees-suffisaient.net/jquery/textgrad.html"&gt;text&lt;/a&gt; (need to test in ie)&lt;/p&gt;  &lt;h3&gt;Menu&lt;/h3&gt;  &lt;p&gt;&lt;a title="http://www.wizzud.com/jqDock/" href="http://www.wizzud.com/jqDock/"&gt;Fisheye&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Picture Gallery&lt;/h3&gt;  &lt;p&gt;&lt;a title="http://www.dfc-e.com/metiers/multimedia/opensource/jquery-fancyzoom/" href="http://www.dfc-e.com/metiers/multimedia/opensource/jquery-Fancyzoom/"&gt;jquery-Fancyzoom&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://benjaminsterling.com/jquery-jqgalscroll-photo-gallery/" href="http://benjaminsterling.com/jquery-jqgalscroll-photo-gallery/"&gt;jqgalscroll-photo-gallery&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://csscody.com/demo/image-slider-player-in-jquery/"&gt;image-slider-player-in-jquery&lt;/a&gt; and here is a &lt;a href="http://csscody.com/demo/wp-content/demo/demo.htm"&gt;demo&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Rounded Corners&lt;/h3&gt;  &lt;p&gt;A nice api &lt;a href="http://plugins.jquery.com/project/corners"&gt;Home&lt;/a&gt;&amp;#160;&lt;a href="http://www.atblabs.com/jquery.corners.html"&gt;Demo&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Really nice to have effect, &lt;a title="http://www.ruzee.com/content/liquid-canvas" href="http://www.ruzee.com/content/liquid-canvas"&gt;liquid-canvas&lt;/a&gt;&amp;#160;&lt;a title="http://www.ruzee.com/files/liquid-canvas/demo.html" href="http://www.ruzee.com/files/liquid-canvas/demo.html"&gt;demo&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://jrc.meerbox.nl/?page_id=4"&gt;jquery-roundcorners-canvas&lt;/a&gt;&amp;#160;&lt;a href="http://jrc.meerbox.nl/demo/"&gt;demo&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://jcorners.culturezoo.com/"&gt;jcorners&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://blue-anvil.com/jquerycurvycorners/test.html" href="http://blue-anvil.com/jquerycurvycorners/test.html"&gt;jquerycurvycorners&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Local scroll&lt;/h3&gt;  &lt;p&gt;&lt;a title="http://demos.flesler.com/jquery/serialScroll/" href="http://demos.flesler.com/jquery/serialScroll/"&gt;serialScroll&lt;/a&gt; nice scroller&lt;/p&gt;  &lt;p&gt;&lt;a title="http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html" href="http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html"&gt;jquerylocalscroll&lt;/a&gt;&amp;#160;&lt;a title="http://demos.flesler.com/jquery/localScroll/" href="http://demos.flesler.com/jquery/localScroll/"&gt;demos&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.gcmingati.net/wordpress/wp-content/lab/jquery/newsticker/jq-liscroll/scrollanimate.html" href="http://www.gcmingati.net/wordpress/wp-content/lab/jquery/newsticker/jq-liscroll/scrollanimate.html"&gt;jq-liscroll&lt;/a&gt;, automatically scrolls text horizontally.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://remysharp.com/2008/09/10/the-silky-smooth-marquee/"&gt;The Silky Smooth Marquee&lt;/a&gt;&amp;#160;&lt;a href="http://remysharp.com/demo/marquee.html"&gt;demo&lt;/a&gt;, it is like list scroller&lt;/p&gt;  &lt;p&gt;&lt;a title="http://jscroller.markusbordihn.de/" href="http://jscroller.markusbordihn.de/example/"&gt;jscroller&lt;/a&gt; scrolls and show html. used for advertisement.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.webinventif.fr/wp-content/uploads/projets/wslide/" href="http://www.webinventif.fr/wp-content/uploads/projets/wslide/"&gt;wslide&lt;/a&gt; (need to test in ie)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-6055484436842109240?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/6055484436842109240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=6055484436842109240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6055484436842109240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/6055484436842109240'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2008/11/collection-of-some-useful-jquery.html' title='Collection of some useful jquery plugins'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-2512683143672634189</id><published>2008-10-22T14:24:00.013+06:00</published><updated>2008-11-21T18:48:52.002+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Facing Issues with migrating rails from 1.2.5 to 2.1.0</title><content type='html'>&lt;p&gt;We identified some issues while porting one of our projects from rails 1.2.5 to 2.1.0&lt;/p&gt;  &lt;h3&gt;Rails removed some functions which were deprecated&lt;/h3&gt;  &lt;p&gt;This affected 3&lt;sup&gt;rd&lt;/sup&gt; party libraries as well as the application to be migrated. As a result we had to tweak some the libraries&lt;/p&gt;  &lt;h3&gt;Application was refactored &lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;rails 1.2.5 supported Project.find_all( :joins=&amp;gt;[&amp;quot;…&amp;quot;], ...) which is now Project.find( :all, :joins=&amp;gt;&amp;quot;...&amp;quot;, ...) &lt;/li&gt;    &lt;li&gt;render '/controller/action' has changed to, render :controller =&amp;gt;'controller', :action =&amp;gt;'action' &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Some libraries are tweaked&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;In-Place-Editing &lt;a href="http://s2.diffuse.it/blog/show/37-in_place_editor_on_rails_2_0_and_rjs_templates"&gt;see&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Regarding Migration&lt;/h3&gt;  &lt;p&gt;The way rails maintained migration information(latest migration) has changed. Rails 1.2.5 kept latest migration version that is synchronized with database in &amp;quot;schema_info&amp;quot; table. And now it stores in &amp;quot;schema_migrations&amp;quot; table.&lt;/p&gt;  &lt;p&gt;&amp;quot; schema_info&amp;quot; has only one row keeping the latest migration synchronized with database. &amp;quot;schema_migrations&amp;quot; has entry for each migration that ran to synchronize the database.&lt;/p&gt;  &lt;p&gt;So if we are migrating to rails 2.1 then we should run an insert script to create entries for each migration in &amp;quot;schema_migrations&amp;quot;.&lt;/p&gt;  &lt;h3&gt;Faced problem with rake 0.8.3&lt;/h3&gt;  &lt;p&gt;We found that rake 0.8.3 creates problem in Linux, so we had to revert the rails version to 0.8.2. Rails 2.1.0 runs with rake 0.8.2.&lt;/p&gt;  &lt;h3&gt;Faced problem with ActiveMessaging&lt;/h3&gt;  &lt;p align="left"&gt;We faced some problem regarding ActiveMessaging. &lt;a href="http://groups.google.com/group/activemessaging-discuss/browse_thread/thread/41989b6599146ba4?pli=1"&gt;Here&lt;/a&gt; is a group discussion that might help. We fixed it by modifying support.rb in activemessaging according to the latest patch, can be found &lt;a href="http://code.google.com/p/activemessaging/source/browse/trunk/plugins/activemessaging/lib/activemessaging/support.rb?spec=svn143&amp;amp;r=143"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Rails 2.1.0 specifies default character set for database&lt;/h3&gt;  &lt;p&gt;Rails 2.1.0 sets utf-8 as default database encoding. So some expected result might misbehave.&lt;/p&gt;  &lt;h3&gt;Faced issues with folder based fixtures&lt;/h3&gt;  &lt;p&gt;Our project had lots of scenario while testing each controller or model. That is why we used folder based fixture so we can concentrate on particular fixture while testing particular model.&lt;/p&gt;  &lt;p&gt;We defined fixture path like,&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;def&lt;/strong&gt; &lt;strong&gt;fixture_path&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;File&lt;strong&gt;.&lt;/strong&gt;join&lt;strong&gt;(&lt;/strong&gt;File&lt;strong&gt;.&lt;/strong&gt;dirname&lt;strong&gt;(&lt;/strong&gt;&lt;strong&gt;__FILE__&lt;/strong&gt;&lt;strong&gt;),&lt;/strong&gt; &amp;quot;../fixtures/test_model&amp;quot;&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;end&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It worked in rails 1.2.5. But it is misbehaving in rails 2.1.0. So we introduced &lt;a href="http://code.google.com/p/fixture-scenarios/"&gt;scenario&lt;/a&gt; plugin to resolve that issue.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-2512683143672634189?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/2512683143672634189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=2512683143672634189' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2512683143672634189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/2512683143672634189'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2008/10/facing-issues-with-migrating-rails-from.html' title='Facing Issues with migrating rails from 1.2.5 to 2.1.0'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-5483460887758582395</id><published>2008-06-04T16:40:00.011+06:00</published><updated>2009-04-12T11:27:23.853+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Object Oriented Design Pattern'/><title type='text'>Template Pattern</title><content type='html'>&lt;p&gt;Template pattern is all about encapsulating algorithm or process. It defines a skeleton of an algorithm with some abstract methods, which allows subclasses to redefine certain steps with out changing the algorithm structure. These abstract methods allow subclasses to be a part of the algorithm so that the pre defined algorithm can be reused.   
&lt;/p&gt;  &lt;h4&gt;Why Template:   
&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Encapsulates algorithm or process, So that it can be reused.     
&lt;/li&gt;    &lt;li&gt;Allows sub classes to be a part of the process, so this pattern is often seen in different frameworks.     
&lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;How to use Template:   
&lt;/h4&gt;  &lt;p&gt;It is a common scenario that we need to authenticate and authorize an user before letting him to execute some secured facility. The user only gets to call the method if he is valid. Here the process sequence is the same. First check if he is valid and then let him execute the method depending on validation. We can encapsulate the process and create "hook up" or "plug in" abstract methods. The client sub class can implement the abstract methods and become part of the process. Here what varies is the logic to verify the user and eventually the logic to execute. So we let the client sub classes to define that part by implementing the abstract methods.   
&lt;/p&gt;  &lt;h4&gt;Class Diagram :   
&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/Ashrafuzzaman.G2/SEluzCNc8yI/AAAAAAAAANs/lYgXQmpdrds/s1600-h/Template%20Pattern%5B3%5D.gif"&gt;&lt;img title="Template Pattern" height="176" alt="Template Pattern" src="http://lh5.ggpht.com/Ashrafuzzaman.G2/SElu0bn2hYI/AAAAAAAAANw/ak_o-guMDuM/Template%20Pattern_thumb%5B1%5D.gif?imgmax=800" width="550" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; 
 &lt;h4&gt;Java Code :   
&lt;/h4&gt;  &lt;h5&gt;AbstractPage.cs   
&lt;/h5&gt;  &lt;pre class="brush: java;"&gt;public abstract class AbstractPage {

   private String userName;

   public void setUserName(String userName) {
       this.userName = userName;
   }

   public void run() {
       //a simple process for validation
       //which is encapsulated in the template class
       if (isValid(userName)) {
           execute();
       }
   }
   //abstract hook up methods which is defined in sub classes

   public abstract boolean isValid(String name);

   public abstract void execute();
}&lt;/pre&gt;&lt;h5&gt;Page.cs &lt;/h5&gt;&lt;pre class="brush: java;"&gt;public class Page extends AbstractPage {

   public boolean isValid(String name) {       //my code to validate user is in here      
       return true;//just a dummy return  
   }

   public void execute() {
       //my code to execute is here  
   }
}&lt;/pre&gt;&lt;h5&gt;TestTemplate.cs &lt;/h5&gt;&lt;pre class="brush: java;"&gt;class TestTemplate {

   private AbstractPage abstractPage;

   public TestTemplate(AbstractPage abstractPage) {
       this.abstractPage = abstractPage;
   }

   public void runProcess() {
       abstractPage.execute();
   }
}&lt;/pre&gt;&lt;h4&gt;Object Oriented Principals used in Template : &lt;/h4&gt;&lt;ol&gt;  &lt;li&gt;The Hollywood principle(don't call us, we'll call you)&lt;/li&gt;
 &lt;li&gt;Code to interface or abstraction not to concrete class.&lt;/li&gt;
 &lt;li&gt;High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.[Dependency Inversion Principal]&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;We see the Hollywood principle in this pattern because the client sub class is being used by the template class. The sub class is being called and becoming part of the process. And eventually the control belongs to the template class.
&lt;/p&gt;&lt;p&gt;The template class is dependent on abstract methods which is later implemented by client sub classes. Template do not have any idea on concrete implementation, it is coded to abstraction. &lt;/p&gt;&lt;p&gt;Dependency Inversion Principal is often used in deferent design patterns. In Template Pattern the high level class is the template class and the implementation is lower level class. Template class is not directly dependent on sub classes rather it is dependent on abstract methods or abstraction. And the client sub class is also dependent on the abstract template class. &lt;/p&gt;&lt;h4&gt;Observation : &lt;/h4&gt;&lt;p&gt;Object oriented pattern is all about encapsulation. Template is a trick to encapsulate process or algorithm, so that the process can be re used, which is achieved by inheritance. But one object oriented principal states that, "prefer composition over inheritance". In template we are using inheritance, which can be replaced by Strategy pattern. A template needs some feed or it needs to provide some hook up, which are achieved by abstract methods. These methods can be interfaced out of the abstract class of Template and convert inheritance in to composition. But it is always a design choice and context dependent decision.&lt;/p&gt;&lt;p&gt;Template is widely used in frameworks for it's ability to allow others to become a part of the system. Similar implementation is seen in Spring controllers, where the frameworks has the control and client controllers are plugged in the system by instantiating the abstract controllers. &lt;/p&gt;&lt;h4&gt;References : &lt;/h4&gt;&lt;p&gt;&lt;a href="http://sourcemaking.com/design_patterns/template_method"&gt;http://sourcemaking.com/design_patterns/template_method&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-5483460887758582395?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/5483460887758582395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=5483460887758582395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/5483460887758582395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/5483460887758582395'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2008/06/template-pattern.html' title='Template Pattern'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/Ashrafuzzaman.G2/SElu0bn2hYI/AAAAAAAAANw/ak_o-guMDuM/s72-c/Template%20Pattern_thumb%5B1%5D.gif?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3260390521541206656.post-8573943592266554556</id><published>2008-06-02T01:25:00.009+06:00</published><updated>2009-04-12T11:41:37.400+06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Object Oriented Design Pattern'/><title type='text'>Strategy Pattern</title><content type='html'>&lt;p&gt;Strategy is one of the elegant design patterns which uses the polymorphism feature of object oriented language. This pattern allows you to change the strategy of how the class will behave at run time, so that your code can keep up with change.   
&lt;/p&gt;  &lt;h4&gt;Why "Strategy" :   
&lt;/h4&gt;  &lt;div style="margin-left: 2em"&gt;   &lt;ol&gt;     &lt;li&gt;Can change how the class will behave at run time       
&lt;/li&gt;      &lt;li&gt;Makes your code reusable and extendable       
&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;  &lt;p&gt;First let's make a simple scenario that is appropriate for us to use Strategy Pattern. Suppose you need to write a simple copy function that copies a file from one place to another. The problem is that your boss wants to support different OS platform. You can say why need strategy I can write a simple code like,   
&lt;/p&gt;  &lt;pre class="brush: java"&gt;public class FileCopier {

   public void copyFile(File source, File destination) {
       if (platform == windows) {
           copyWindowFile(source, destination);
       } else if (platform == linux) {
           copyLinuxFile(source, destination);
       }
   }

   public void copyWindowFile(File source, File destination) {
       //here is your windows copy code 
   }

   public void copyLinuxFile(File source, File destination) {
       //here is your Linux copy code 
   }
}&lt;/pre&gt;&lt;p&gt;Now what if your boss tells you to add support for Mac OS. Then you will have to change the FileCopier class and re-test it. This surely will not make your boss happy as FileCopier is a very important class and people don't want it to change. One other thing is that change in FileCopier class to add support for Mac will also impact the software for other platforms, which is not desired.

&lt;/p&gt;&lt;p&gt;One of the key feature of using real good object orientation is that it reduces change. And adding endless if-else block will make your code lengthy and fragile and you will also face the wrath of the other programmer who might have to change your code.

&lt;/p&gt;&lt;h4&gt;How to use "Strategy" :

&lt;/h4&gt;&lt;h4&gt;Class Diagram:&lt;/h4&gt;&lt;h4&gt;&lt;a href="http://lh4.ggpht.com/Ashrafuzzaman.G2/SElmjRfh2OI/AAAAAAAAANk/1rGN7ojRk-o/s1600-h/Strategy%5B3%5D.gif"&gt;&lt;img title="Strategy" height="102" alt="Strategy" src="http://lh6.ggpht.com/Ashrafuzzaman.G2/SElmlBegQ4I/AAAAAAAAANo/8boOXiijQMg/Strategy_thumb%5B1%5D.gif?imgmax=800" width="550" border="0" /&gt;&lt;/a&gt;&lt;/h4&gt;&lt;h4&gt;Java Code:
&lt;/h4&gt;&lt;h5&gt;IFileCopier.java: &lt;/h5&gt;&lt;pre class="brush: java"&gt;public interface IFileCopier {
   void copyFile(File source, File destination);
}&lt;/pre&gt;&lt;h5&gt;WindowsFileCopier.java
&lt;/h5&gt;&lt;pre class="brush: java"&gt;public class WindowsFileCopier implements IFileCopier {

   public void copyFile(File source, File destination) {
       //copy file in Window machine
   }
}&lt;/pre&gt;&lt;h5&gt;LinuxFileCopier.java
&lt;/h5&gt;&lt;pre class="brush: java"&gt;public class LinuxFileCopier implements IFileCopier {

   public void copyFile(File source, File destination) {
       //copy file in Linux machine
   }
}
&lt;/pre&gt;&lt;p&gt;When IFileCopier is used in any context, it is coded using the interface IFileCopier. So it works for all the implementations of IFileCopier. When you will pass an instance of LinuxFileCopier it will have the behavior of copying file in Linux and an instance of WindowsFileCopier it will have the behavior of copying file in Windows. Now you can create another implementation of IFileCopier and pass the new implementation. As long as your implementation is OK the existing code will be OK : ). So here you are actually reducing the amount of change in existing code. So the amount of test is reduced and you can cope up with the change faster.

&lt;/p&gt;&lt;h4&gt;Object Oriented Principals used in Strategy :
&lt;/h4&gt;&lt;blockquote&gt;&lt;p&gt;1. Code to interface or abstraction not to concrete class.
2. High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.[Dependency Inversion Principal]
3. Single Responsibility Principal(SRP)
4. Encapsulate what varies from what stays the same &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;We see the first principal in Context class as there we did code to interface(IFileCopier). Context is high level class and WindowsFileCopier or LinuxFileCopier is lower level class as Context uses them. But Context is actually dependent on an interface not to a concretion. So Strategy follows Dependency Inversion Principal.

 Single Responsibility Principal states that, "a class should have only one reason to change". In other words a class should do one thing and do it very well. Here we used this principal as we separated the OS dependant logic to separate class. So change in one part will not effect change in other parts.

   One other important thing is that we should identify parts that varies in a system. So that we could encapsulate what varies from what stays the same. Here we encapsulated the behavior to copy files, so that it could give us flexibility to re use it to support different OS platform. This will allow us to minimize change and maximize flexibility.

&lt;/p&gt;&lt;h4&gt;References:
&lt;/h4&gt;&lt;a href="http://sourcemaking.com/design_patterns/strategy"&gt;http://sourcemaking.com/design_patterns/strategy&lt;/a&gt;
&lt;a href="http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/StrategyPattern.htm"&gt;http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/StrategyPattern.htm&lt;/a&gt;
&lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;http://en.wikipedia.org/wiki/Strategy_pattern&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3260390521541206656-8573943592266554556?l=jitu-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jitu-blog.blogspot.com/feeds/8573943592266554556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3260390521541206656&amp;postID=8573943592266554556' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8573943592266554556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3260390521541206656/posts/default/8573943592266554556'/><link rel='alternate' type='text/html' href='http://jitu-blog.blogspot.com/2008/06/strategy-pattern.html' title='Strategy Pattern'/><author><name>A.K.M. Ashrafuzzaman</name><uri>https://profiles.google.com/104367174527608513550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-Qz6xmvnmVDc/AAAAAAAAAAI/AAAAAAAAM_M/L833HP2Suxg/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/Ashrafuzzaman.G2/SElmlBegQ4I/AAAAAAAAANo/8boOXiijQMg/s72-c/Strategy_thumb%5B1%5D.gif?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry></feed>
