I came across an interesting article by Fred Wilson:
http://thinkvitamin.com/business/fred-wilsons-10-golden-principles-of-successful-web-apps/
I stumbled across a situation when I have to schedule a job and I have to store today's weekday. I am also storing the schedule's created_at/ updated_at time in datetime format.
To store today's weekday, I said:
weekday = Time.now.wday
>> 4 #Thursday
When I stored the record
Schedule.first.created_at.wday
>> 3 #Wednesday
Why?
I dug in more and here are the facts.
We so say in environment.rb file:
config.time_zone = 'UTC'
But this applies to only the created_at/updated_at attributes and sets up the default timezone for the database and never applies to Time.now
So to keep Time.now in sync we have to set ENV['TZ'] in environment.rb file.
Again in console:
weekday = Time.now.wday
>> 3 #Wednesday
Schedule.first.created_at.wday
>> 3 #Wednesday
:)
I think I have never encountered this issue until today. On my current Ruby on Rails project I am using Oracle as the database. I have a user model, which has an attribute email and the requirement was that a user can have more than one email id (separated by comma). I initially thought that I should use :text type, as I literally forgot that I am writing a migration against oracle database. Later, when the actual requirement come into the picture, I had to revise as user can have just one email-id and I started thinking about changing the type from :text to string.
There were two reasons to change the column type:
1. As per the requirement, user cannot have so many email-ids
2. Changing the column type from clob to string in oracle would give good performance boost
I decided to change the column type by simply using :
change_column :users, :email, :string, :limit => 4000
D:\rubyapp>rake db:migrate
(in D:/rubyapp)
== ChangeEmailColumnTypeToStringInUsers: migrating ===========================
-- change_column(:users, :email, :string, {:limit=>4000})
rake aborted!
An error has occurred, all later migrations canceled:
OCIError: ORA-22859: invalid modification of columns: ALTER TABLE users MODIFY email VARCHAR2(4000)
(See full trace by running task with --trace)
Failed! But why?
I came across: http://snippets.dzone.com/posts/show/3022
I followed the same pattern:
1. Add a temporary column with type as string (varchar2 in local)
2. Update all the records and copy text from email column to temporary column
3. Remove email column
4. Rename temporary column to email
I decided to not to run oracle commands in migration.
Here is how my migration now looks like:
class ChangeEmailColumnTypeToStringInUsers < ActiveRecord::Migration
def self.up
add_column :users, :email_temp, :string, :limit => 200
User.all.each do |user|
user.update_attribute("email_temp", user.email)
end
remove_column :users, :email
rename_column :users, :email_temp, :email
end
def self.down
add_column :users, :email_temp, :text
User.all.each do |user|
user.update_attribute("email_temp", user.email)
end
remove_column :users, :email
rename_column :users, :email_temp, :email
end
end
Very simple!
I was looking for a ruby method in my Ruby on Rails project which can truncate a string, say after 50 characters.
I found 'truncate' method, which is a rails api method for truncating string in views.
So if have string
str = "Hi, this is Gourav Tiwari, how are you??" # total 40 characters
the truncate method can be used in the ciew like this:
truncate(str, :length => 25, :ommision => " - - -")
and the result would be :
"Hi, this is Gourav Tiwari, - - -"
In ruby I can accomplish same by slice and concatenation:
myproject>ruby script\console
>> str = "Hi, this is Gourav Tiwari, how are you??"
=> "Hi, this is Gourav Tiwari, how are you??"
>> str.slice(0..25)
=> "Hi, this is Gourav Tiwari,"
>> str.slice(0..25) + " - - -"
=> "Hi, this is Gourav Tiwari, - - -"
Very simple!
Playing more on JQgrid plugin from 2dconcept, I faced a strange issue. Sometimes it skips some pages.
For example if you have total 15 pages, and you navigate till 6th page and then you hit next page button on the grid, it will not show you the 7th page! you have to click next page button once more to see the 8th page. So where the 7th page is gone?
No, it's not invisible, it's all hidden in json response.
When I saw the response for page 7 (using firbug), it was coming well, but the grid was not showing the 7th page at all. I dug into the library file more and figured out that, if in the response you have a double quote, it will not display that page.
Say you have this json response:
{"page":"1","total":1,"records":"1","rows":[{"id":"7","cell":["gourav tiwari hel"lo!","this","should","be right!"]}]}
See the double quote in the response.
I tried using to_json library method, but it actually removes all the double quotes, even the necessary ones as well. So not a good idea. I extended to_jqgrid_json method like this:
module JqgridJson
def to_jqgrid_json(attributes, current_page, per_page, total)
json = %Q({"page":"#{current_page}","total":#{total/per_page.to_i+1},"records":"#{total}")
if total > 0
json << %Q(,"rows":[)
each do |elem|
elem.id ||= index(elem)
json << %Q({"id":"#{elem.id}","cell":[)
couples = elem.attributes.symbolize_keys
attributes.each do |atr|
value = get_atr_value(elem, atr, couples)
value = value.is_a?(String) ? value.gsub(/"/, '\"') : value # added this line
json << %Q("#{value}",)
end
json.chop! << "]},"
end
json.chop! << "]}"
else
json << "}"
end
end
end
And the response become this:
{"page":"1","total":1,"records":"1","rows":[{"id":"7","cell":["gourav tiwari hel\"lo!","this","should","be right!"]}]}
No invisible page in JQGrid anymore!
In one of my earlier projects, there was a requirement from product owners, to show data in grid format. It was way back in summar of 2008. We had to load the whole data by hand-coding the trs and tds in table and shown the results in html table's grid format.
Back to the current project, I did a little research and found jquery-grid-rails-plugin
I found it pretty useful and up to the mark as far as results are being displayed on the Grid (AJAX calls). You can look at the Demo as well (http://github.com/ahe/jqgrid_demo_app/tree/master), also a detailed explanation on installation and usage mentioned here -> http://www.2dconcept.com/jquery-grid-rails-plugin
The response is pretty quick, from 1000 records in DB to fetch 25 on one page it took around 500 ms. Also, you can use various JQuery themes if you do not like the default look and feel: http://jqueryui.com/themeroller
Lets take a very small example and see how to use JQgrid:
I have User controller's index method to write logic to display all users.
User model has attributes as:
id : integer (row id)
name : string
created_at : date
I have User's view (users/index.html.erb file) to display the grid with above attributes.
Steps:
1. Install plugin: $ ./script/plugin install git://github.com/ahe/2dc_jqgrid.git
2. In layout include JS and CSS for grid:
<%= jqgrid_stylesheets %>
<%= jqgrid_javascripts %>
3. In User controller:
def index
users = User.find(:all) do
if params[:_search] == "true"
name =~ "%#{params[:name]}%" if params[:name].present?
created_at =~ "%#{params[:created_at]}%" if params[:created-at].present?
end
paginate :page => params[:page], :per_page => params[:rows]
order_by "#{params[:sidx]} #{params[:sord]}"
end
respond_to do |format|
format.html
format.json { render :json => users.to_jqgrid_json([:id, :name, :created_at], params[:page], params[:rows], users.total_entries) } # total entries will get User.all.size
end
end
4. In view:
<%= jqgrid("All users", "users", users_url, # my recommendation as putting /users sometimes does not work in all cases
[ { :field => "id", :label => "ID", :width => 35, :resizable => false },
{ :field => "name", :label => "User Name" },
{ :field => "created_at", :label => "Created on" }
]
) %>
Now everything is fine, it should work fine and show us the grid with name and created at time.
Problem that I faced: When you have to show any attribute of model with formatting , there was nothing mention on the blog, like I would like to Capitalize the name here in the grid (First letter is capital).
So, I dug into the code and found my solution
Solution:
In index I have to change the format.json in index method like this:
render :json => users.to_jqgrid_json([:id, "name.capitalize", :created_at], params[:page], params[:rows], users.total_entries)
and in view I need to change following line as :
{ :field => "name.capitalize", :label => "User Name" },
and it works!
Another problem: If I need to change the format of the created_at, can I do this in controller and view?
Controller:
render :json => users.to_jqgrid_json([:id, "name.capitalize", 'created_at.strftime("%Y-%m-%d")'], params[:page], params[:rows], users.total_entries)
View:
{ :field => "name.capitalize", :label => "User Name" },
{ :field => 'created_at.strftime("%Y-%m-%d")', :label => "Created on" }
Answer is NO.
Because, the way jqgrid ruby plugin written, you cannot use method with parameters.
Solution: I used instance method.
In model, I wrote:
def formatted_created_at
created_at.strftime("%Y-%m-%d")
end
def capitalized_name
name.capitalize
end
In controller:
render :json => users.to_jqgrid_json([:id, :capitalized_name, :formatted_created_at], params[:page], params[:rows], users.total_entries)
In view:
{ :field => "capitalized_name", :label => "User Name" },
{ :field => "formatted_created_at", :label => "Created on" }
That's it!
Browsing through various blogs about client side technologies, I came across something interesting:
http://thinkingrails.blogspot.com/2008/01/top-ten-mistakes-in-web-design.html
I never realized that HTML is so powerful. With it's latest version HTML 4.0.1 released way back in 1999, it has several features, which makes HTML another important ingredient in Client-side Technologies.
HTML is a language, which is today understood by all browsers(rendering engine) and the rendering engine of browser converts this code in HTML in graphics.
A brief description of HTML and history can be find here
HTML version 4 is there for quite sometime and has several features (refer to http://htmlhelp.com/reference/html40/new.html): There are some new elements added like ABBR, IFRAME, BUTTON, OBJECT, SPAN, TBODY, etc now integral part of web page development.
Key Features:
1. Separation of Structure and Presentation: Now you can use same structure of web content and achieve different look and feel. This is important because you need different presentations on different devices of latest technologies, for exanple rails application on laptop and mobile needs different presentation.
2. Accessibility: With addition of elements like IFRAME, TBODY, SPAN, FIELDSET, etc, and the freedom from device/structure the web has now more clear outlook and have more bigger set of users (including users having low-vision, blindness, color-blindness with different browsing environments, large fonts, special colors, speech synthesizers, and Braille tactile feedback devices.
3. Internationalization: With rich Universal Character Set, HTML 4.0 supports almost all of the world's language.
4. Style Sheets: New hooks for CSS like ID, STYLE and CLASS help in attaching different styles. Also, MEDIA can be used to specify media and TYPE for style sheet language.
5. Client side scripting: SCRIPT element allow you to add client side scripting using LANGUAGE attribute. NOSCRIPT element also included in case any broser does not support the scripting or user disable the scripting in browser.
6. Frames: It gives developers a freedom to use multiple documents in a single window, i.e. multiple independent windows or subwindows in a single window(web page).
Multiple views offer designers a way to keep certain information visible, while other views are scrolled or replaced. For example, within the same window, one frame might display a static banner, a second a navigation menu, and a third the main document that can be scrolled through or replaced by navigating in the second frame.
7. Advanced Tables: You can group rows and columns together, i.e. by using row groups (THEAD, TFOOT, TBODY) you can render static header and footer rows with scrollable body rows.
And, HTML 5.0 Well not very near, if you believe on sources online it will take 10-12 years more to have a latest HTML version officially!
So, what's new in HTML 5.0? It will support various new elements and browsers like firefox, opera, safari, etc started supporting these elements now.
At the same time it will be backward compatible.
Several new APIs for better web application design:
* 2D drawing API which can be used with the new canvas element.
* API for playing of video and audio which can be used with the new video and audio elements.
* An API that enables offline Web applications.
* An API that allows a Web application to register itself for certain protocols or media types.
* Editing API in combination with a new global contenteditable attribute.
* Drag & drop API in combination with a draggable attribute.
* API that exposes the history and allows pages to add to it to prevent breaking the back button.
* Cross-document messaging.
New elements provide additional features, like ruby, rt and rp allow for marking up ruby annotations.
Here is a quick reference to find difference in HTML 5.0 and 4.0
Interesting features! Well I am not stopping here.. next will be XML.
To begin with Latest Technologies at client side, let's pick simplest but important one: Browser
Browser, i.e. Web browser, is a software application used to locate and display Web pages, typically html pages. Browsers now a days provide features, such as display graphics, images, play video and so on.
But how it works?
When user type a url in address bar, Browser identifies the protocol (generally http), the server name(which is mapped to DNS at the World Wide Web which is a system of internet servers) and the content user is requesting.
From Webopedia: "In order for your browser to actually connect to the Web server to retrieve the information you request, it communicates with a name server to translate the server name into an IP address. Your Web browser is then able to connect to the Web server at the resolved IP address on port 80. Once your browser has connected to the Web server using HTTP, the browser then reads the HyperText Markup Language (HTML), the authoring language used to create documents on the World Wide Web, and the data is then displayed in your Web browser."
Browser displays the web page by rendering engine. A rendering engine is a program that interprets code and markup languages (such as HTML or XSL) and generates the image of the Web page you see in your Web browser.
Gecko is known as rendering/layout engine for Firefox. It is written in C++ and is cross-platform, and runs on various operating systems including BSDs, Linux, Mac OS X, Solaris, OS/2, AIX, OpenVMS, and Microsoft Windows. Similarly, Trident(also known as MSHTML), rendering engine for IE.
Interestingly, Firefox is #1 browser at present(http://internet-browser-review.toptenreviews.com) with hundreds of plug-ins, various themes and features:
In terms of popularity, Firefox has beaten it's rival IE combinding IE6, IE7 and IE8 statistics (Source W3Schools). Facts say that almost 50 % internet users use Firefox!
Comparing between several web browsers over security, features, UI, etc. Firefox seems more promising than any other browsers. What say?
I started reading about client-server model for web applications, again.
I wonder, since this model evolved back in 70's and 80's, how many technologies, platforms, etc ccome in.
When I think about the client-server model for web application, few things are obvious:
1. Browser (Firefox, IE, Google Chrome, Safari, etc)
2. HTML, CSS and Java Script
3. Scripting Languages (PHP, Ruby, etc)
4. Latest concepts for RIA (AJAX, Flash, Flex, Silverlight, etc)
5. Others
In my quest to find out, the latest technologies related to Client-Server model for web applications, I'll understand various aspects of these technologies and pros and cons of them.
I'll start from Client side technologies first...
I came to know about blogs and wikis two years ago, when I first heard of Web 2.0. Since then, I saw drastic changes in web. Last month I heard something about Web 3.0, I realized that the way web is going, it's obvious to have various versions coming so frequently :) But still I had some unanswered questions :
December, 23rd, 2008 will be remembered as the most important day in Ruby on Rails history. Merb is, a framework, dedicated for developers. It gives power to build and choose your own tools. On the other hand Rails community is rich with great features in the kitty and well prepared for Rails-2.3 launch in January, 2009 with new features(Rails Metal, application generators, etc).
But, both the sides of fence share a common goal: help developers to write better performing application, easily. That's where Rails 3 + Merb 2 comes in :)
Cucumber is one of the cornerstone for BDD in Ruby on Rails. Non technical or business participants can write tests (called as features or stories) in plain English and cucumber allows the developers to execute these tests.
I was very excited when I started looking at it. In my test.feature file, I have a feature:
Feature: Grant and revoke access
To have proper security model
User should have proper access
Scenario: Revoke access of a user who do not deserves access
Given Gourav is a user who do not deserves access
When system run cron job to verify access
Then Gourav's access should be revoked
There are two ways to execute this file:
1. Cucumber as a plugin (by rake task):
It starts eating 'a' and 'A' characters on windows:
Feture: Grnt nd revoke ccess # fetures/grnt_nd_revoke_ccess.feture
To hve proper security model
User should hve proper ccess
Scenrio: Revoke ccess of user who do not deserves ccess # fetures/test.feture:5
Given Gourv is user who do not deserves ccess # fetures/test.feture:6
When system run cron job to verify ccess # fetures/test.feture:9
Then Gourv's ccess should be revoked # fetures/test.feture:10
cucumber features\test.feature It gives: Feature: Grant and revoke access # features/test.feature
To have proper security model
User should have proper access
Scenario: Revoke access of a user who do not deserves accessC:/ruby/lib/ruby/gems/1.8/
gems/cucumber-0.1.12/bin/../lib/cucumber/tree/scenario.rb:70:in length': undefined methodjlength' for Scenario ng (NoMethodError)
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/tree/scenario.rb:74:in `max_line_length'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/tree/scenario.rb:78:in `padding_length'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/formatters/pretty_formatter.rb:197:in `padding_spaces'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/formatters/pretty_formatter.rb:58:in `scenario_executing'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/broadcaster.rb:15:in `__send__'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/broadcaster.rb:15:in `method_missing'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/broadcaster.rb:13:in `each'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/broadcaster.rb:13:in `method_missing'
... 12 levels...
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/../lib/cucumber/cli.rb:11:in `execute'
from C:/ruby/lib/ruby/gems/1.8/gems/cucumber-0.1.12/bin/cucumber:6
from C:/ruby/bin/cucumber:19:in `load'
from C:/ruby/bin/cucumber:19
I found a workaround for this:
In file C:\ruby\lib\ruby\gems\1.8\gems\cucumber-0.1.12\lib\cucumber\tree\Scenario.rb on line number 69, I have changed jlength to length:
@length ||= Cucumber.language['scenario'].length + 2 + (@name.nil? ? 0 : @name.length)
Similarly, in file C:\ruby\lib\ruby\gems\1.8\gems\cucumber-0.1.12\lib\cucumber\tree\step.rb on line number 22 I have changed jlength to length:
keyword.length + 1 + name.length
But for a better solution I am still working on issue #81
India's economy capital - Mumbai, faced world's worst terror attack. I was following the news channels for almost three days and every time, I heard a casualty of hostages, Cops or Commandos, it hurt me even more.
Then I thought, why can't we fight the terror in more organized way? Why these people who have no religion are killing us, the common man, like we do not exist and still, we are not able to take any step towards our security? I do not think that entire responsibility for security is on Government of India or on our brave Police officers or on Army. It's responsibility of every individual. System is there to help us but in turn even they need our helping hands to fight against this brutality.
While, speaking to one of my friend, I asked him all these quesions and he said, "What should we do?" and for my surprise, I did not have answer to that question on top of my head. I thought through it and got some ideas, though may be a waste, but that's what I can think of:
1. Since mostly these terrorists try to stay in colonies, so that they will become a part of public,
in a colony, people should unite and they should report any new person coming in their colony to Police.
2. Police should check the background of each person, even though this is done in most of the socities in mumbai, but again this should be done strictly.
3. People should try to keep an eye on new people, they should be polite with everyone but they have to verify each person in a way, that should not hurt the new person.This point is very important, this should not become a way to offend a person on racial or cast or religion basis.
4. These terrorists may stay in hotels, every hotel should be provided metal detectors, it may cost some bucks to Government. but it can help immensely.
5. Goverment should come ahead and set a deadline, by which each person in india should get some kind of Identity card. People without identity card, should get very limited benifits.
I am not saying this will kill terrorism, because these terror attacks happened in evry part of the world, no matter how secure the place is, but these ways will definately make some impact, rather than sitting idle. None of the steps I mentioned, will make india terror free in a day, but I hope gradually it will. And above all, it's responsibilty of individuals to secure themselves and people have to help each other.
Recently, I joined a new project. Before I get started, my tech lead asked me to go through the code first and find complex parts of it, so that during development I will be careful about those areas.

In my last project, I worked as a developer on "Ruby on Rails". The software methodology was Agile (Scrum). Scrum is an iterative incremental process of software development commonly used with agile software development).We particularly picked up 1 week iteration (which is called "1 week sprint").
But why 1 week sprint?
I was suspicious whether 1 week iteration would be successful. It works this way, end of every one week development team has to show running and production deliverable code and so on, until the final iteration, when client team(Product Owner(s)) says, that this is the product I want.
Advantage is, the client team have much closer look what functionality they want and they get, so they can ask development team to implement those functionality which are more of client's interest. Every week they can prioritize the items and development team work on high priority items only.
And how Ruby On Rails fit in this picture?
I did not realized this until the last 4-5 sprints, when all of sudden our client team said that they want to modify the core business logic. I thought, is it possible to implement the change when everything is developed and software is 90% ready? And then, we relied upon unit testing with Rspec (see Behavior-driven testing with RSpec) and functional testing by Rspec stories(see telling stories by Rspec).
With unit testing in place covering more than 85% code, we were assured that the changes will go smoothly. Rspec stories on the functional side, assured us that business logic would be as per the client team's need.
Learning & Best Practices:
In the retrospective of the project, I noted following things which can be useful for other projects: