Friday, September 28, 2007

swf chart vs gruff

Need to evaluate them when I get some time. Requested Geoff to produce a screencast on Selenium on Rails. He responded back after a few days saying he has to learn it and has included it in this todo list.

Ruby Idioms Presentation

Here is the link to the presentation. Thanks to Pelle for his review on his website.

Thursday, September 20, 2007

How to use Will Paginate 2.0 Rails plugin

Step 1: In the controller:
@users = User.paginate(:order => 'created_at DESC'
:conditions => ["active = ?", 1]
:per_page => 10,
:page => params[:page])

Step 2: In the view:
<%= will_paginate @users, :inner_window => 10, :outer_window => 10 %>

This will create page links from 1 to 10 then dots followed by numbered links for last 10 pages.

Step 3: To make the pagination links sexy, copy the following CSS (Digg style):

div.pagination {
padding: 3px;
margin: 3px;
}

div.pagination a {
padding: 2px 5px 2px 5px;
margin: 2px;
border: 1px solid #AAAADD;

text-decoration: none; /* no underline */
color: #000099;
}
div.pagination a:hover, div.pagination a:active {
border: 1px solid #000099;

color: #000;
}
div.pagination span.current {
padding: 2px 5px 2px 5px;
margin: 2px;
border: 1px solid #000099;

font-weight: bold;
background-color: #000099;
color: #FFF;
}
div.pagination span.disabled {
padding: 2px 5px 2px 5px;
margin: 2px;
border: 1px solid #EEE;

color: #DDD;
}

Reference: Err the blog.

Tuesday, September 18, 2007

San Francisco Ruby Meetup

I presented my Ruby Idioms today at the San Francisco Ruby Meetup. It was my first presentation and I was very excited. It was full of examples and practical tips. Some of the idioms were described in the context of Rails applications. Soon I will be posting the link to the actual presentation in pdf format. Enjoy!

Tuesday, August 28, 2007

Rails Performance Notes

Static Caching

- Cache on demand through Rails
- Cron sweeper (minute.rb?)
- JS + cookie for username
- Caching functional test
- ngnix config (run it locally for testing?)
- deploying cron job


Performance

1. Query optimization - query analysis (doing n queries instead of joins)
2. Rails static page caching
3. Asset packager - Firebug Net tab (Page lead times, "apparent" performance)
4. Number of optimal Mongrels ( Topfunky screencast )
5. Rails log - Page load times, Query times
6. Unix diagnostics
- Top
- Vmstat
- MySQL tools
- tail / grep etc
7. Periodic reporting
8. Benchmarks

Friday, August 17, 2007

PostgreSQL on Mac OS

MySQL suddenly stopped working and I was not able to run it. I got frustrated with MySQL error messages like no /tmp/mysql.sock found and -bash: /usr/local/mysql/bin/mysql: Bad CPU type in executable

22:04:59:/usr/local/src > mkdir postgres
22:05:24:/usr/local/src > cd postgres/
22:05:27:/usr/local/src/postgres > ls -l
22:05:29:/usr/local/src/postgres > curl -O ftp://ftp5.us.postgresql.org/pub/PostgreSQL/source/v8.2.4/postgresql-8.2.4.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14.8M 100 14.8M 0 0 48521 0 0:05:21 0:05:21 --:--:-- 77126
22:12:19:/usr/local/src/postgres > tar -xzvf postgresql-8.2.4.tar.gz
postgresql-8.2.4

22:31:26:/usr/local/src/postgres > cd postgresql-8.2.4
22:31:30:/usr/local/src/postgres/postgresql-8.2.4 > ./configure --with-includes=/sw/include/ --with-libraries=/sw/lib
checking build system type... powerpc-apple-darwin8.10.0

22:33:12:/usr/local/src/postgres/postgresql-8.2.4 > make
22:41:07:/usr/local/src/postgres/postgresql-8.2.4 > sudo make install
23:25:46:/usr/local/src/postgres/postgresql-8.2.4 > /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the -A option the
next time you run initdb.

Success. You can now start the database server using:

/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
or
/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start

23:29:07:/usr/local/src/postgres/postgresql-8.2.4 > /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
LOG: database system was shut down at 2007-08-16 23:26:25 PDT
LOG: checkpoint record is at 0/42BEB8
LOG: redo record is at 0/42BEB8; undo record is at 0/0; shutdown TRUE
LOG: next transaction ID: 0/593; next OID: 10820
LOG: next MultiXactId: 1; next MultiXactOffset: 0
LOG: database system is ready

23:35:06:~ > /usr/local/pgsql/bin/createdb
CREATE DATABASE
23:35:33:~ > /usr/local/pgsql/bin/createdb mytestdb
CREATE DATABASE
23:35:45:~ > /usr/local/pgsql/bin/psql mytestdb
Welcome to psql 8.2.4, the PostgreSQL interactive terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit

mytestdb=# create table foo(name varchar primary key, foo_id serial);
NOTICE: CREATE TABLE will create implicit sequence "foo_foo_id_seq" for serial column "foo.foo_id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
CREATE TABLE
mytestdb=# insert into foo(name) values ('Liz');
INSERT 0 1
mytestdb=# insert into foo(name) values ('Bunny');
INSERT 0 1
mytestdb=# select * from foo;
name | foo_id
-------+--------
Liz | 1
Bunny | 2
(2 rows)

Sunday, August 12, 2007

Acts as Billable Installation

1. script/plugin install http://source.collectiveidea.com/public/acts_as
_billable/trunk/

2. script/plugin install http://activemerchant.googlecode.com/svn/trunk/
active_merchant

3. sudo gem install --source http://dist.leetsoft.com money

4. script/plugin install http://source.collectiveidea.com/public/rails/p
lugins/acts_as_money

Monday, July 30, 2007

How to add Rails plugin files to SVN during install

use -x flag. Example:

script/plugin install -x http://svn.techno-weenie.net/projects/plugi
ns/restful_authentication/

Tuesday, July 24, 2007

Recurring Billing in Rails

Research notes:

Dealing with subscriptions payment
Follow-up to subscriptions
Recharging to the Same Credit Card

Sample test case:

def test_reference_purchase
assert response = @gateway.purchase(Money.new(10000), @creditcard, @options)
assert_equal "Approved", response.message
assert response.success?
assert response.test?
assert_not_nil pn_ref = response.authorization

# now another purchase, by reference
assert response = @gateway.purchase(Money.new(10000), pn_ref)
assert_equal "Approved", response.message
assert response.success?
assert response.test?
end

Acts As Billable Plugin

script/plugin install http://source.collectiveidea.com/public/acts_as_billable/trunk/
There’s a start of a sample app (that uses rspec) that goes with it at http://source.collectiveidea.com/public/acts_as_billable/samples/depot

Authorize.Net Automated Recurring Billing (ARB) Example Code

ARG Guide

Tuesday, July 17, 2007

Help in writing tests in Rails

script/console test

It will load the console in the test environment. Very useful to experiment with the code and write tests.

Saturday, July 14, 2007

Railscookbook example error

NameError in User#list_perms

Showing app/views/user/list_perms.rhtml where line #22 raised:

uninitialized constant UserHelper::Permission

create the permission model without migration.

Also the migration for permissions table does not have a id column. This results in a bug where the update does not work for some cases. So I had to add a primary key column to the permissions table. This fixed the buggy update problem.

How to skip migration in Rails

use --skip-migration switch: Ex: script/generate model user --skip-migration

Thursday, July 05, 2007

How to suppress rendering of layout while generating xml in Rails

def my_xml_method
@foo = Foo.find(:all)
render :layout => false
end

If you have render and respond_to in the same method, you will get the dreaded double render error.

Wednesday, July 04, 2007

How to install RubyInline in Mac OS

$ sudo gem install rubyinline
Successfully installed RubyInline-3.6.3
Installing ri documentation for RubyInline-3.6.3...
Installing RDoc documentation for RubyInline-3.6.3...

Port install did not work:

sudo port install rb-rubyinline
---> Fetching autoconf
---> Attempting to fetch autoconf-2.61.tar.bz2 from http://ftp.gnu.org/gnu/autoconf
---> Verifying checksum(s) for autoconf
---> Extracting autoconf
---> Configuring autoconf
---> Building autoconf with target all
---> Staging autoconf into destroot
---> Installing autoconf 2.61_0
---> Activating autoconf 2.61_0
---> Cleaning autoconf
---> Fetching rb-rubygems
---> Attempting to fetch rubygems-0.9.4.tgz from http://rubyforge.org/frs/download.php/20989/
---> Verifying checksum(s) for rb-rubygems
---> Extracting rb-rubygems
---> Configuring rb-rubygems
Error: Target com.apple.configure returned: configure failure: shell command " cd "/opt/local/var/db/dports/build/_opt_local_var_db_dports_sources_rsync.rsync.darwinports.org_dpupdate_dports_ruby_rb-rubygems/work/rubygems-0.9.4" && /opt/local/bin/ruby -rvendor-specific setup.rb config " returned error 127
Command output: sh: line 1: /opt/local/bin/ruby: No such file or directory

Error: The following dependencies failed to build: rb-hoe rb-rake rb-rubygems rb-rubyforge
Error: Status 1 encountered during processing.

How to use select_tag to create drop down menus in Rails

<%=
select_tag :size, options_for_select(["Small", "Medium", "Large"])
%>

This will create a drop down with the values in the array. You can either declare a constant array in the model and use that like: MyModel::SHIRT_SIZES instead of hard coding it. If it is database driven, write a helper that will return an array of options.

Sunday, July 01, 2007

How to find the helper methods for RESTful nested routes in Rails


1) script/console
2) >> irb ActionController::Routing::Routes
3) rs = ActionController::Routing::Routes
4) rs.named_routes.each {|name, route| puts( name, route) }; 1
5) Just copy the list of helper methods show in the output of step 4 and append path to that name. You must also provide the required ids shown in the output. For example take the output:

user
GET /users/:id/ {:action=>"show", :controller=>"users"}

and in the console, type:

>> user_path 1
=> "/users/1"

The same process can be used for nested routes.

Reference: Rails Routing by David A Black. This book gave me a solid understanding of routes.

Friday, June 29, 2007

Difference between capitalize and humanize in Rails

From the script/console:

>> t = "test"
=> "test"
>> t.capitalize
=> "Test"
>> t.humanize
=> "Test"
>> c = "foo bar"
=> "foo bar"
>> c.humanize
=> "Foo bar"
>> c.capitalize
=> "Foo bar"

How to use hidden field in Rails

<%= f.hidden_field :user_id, :value => current_user.id %>

This passes a hidden variable user_id with the value of current_user.id

Thursday, June 28, 2007

Displaying time only in Rails

Not well documented in the Rails API. Here it is:

<%= f.datetime_select(:time, :discard_day => true, :discard_month => true, :discard_year => true) %>

How to create admin accounts in Rails app

The Memphisto source has rake db:bootstrap task that I use for loading admin users into the database. The dynamic fixture allows using any user and password for a admin account.

Wednesday, June 27, 2007

How to freeze gems using Rake

1. script/plugin install http://svn.ardes.com/rails_plugins/gems
2. rake gems:freeze GEM=gem_name

Monday, June 25, 2007

Migrating Local Subversion Repository to Remote Repository

I have been developing the Rails app on my Powerbook using Subversion with file:/// protocol. So when I had to migrate it to Subversion repository hosted remotely by Rimu I had to do the following:

1) On the laptop:

svnadmin dump ~/home/path/to/svn/repos > some-file-name

2) I used Transmit FTP client to use SFTP to the remote host and copied the some-file-name to the remote machine.

3) Login to the remote machine and run:

svnadmin load subversion-repo-name < some-file-name

I created a new directory on my laptop and did a checkout from remote repository:
svn co --username some_user --password some_password http://www.your-domain.com/project_name/trunk

then svn info shows that the repository is http:// pointing to the remote repository.

svn log http://www.your-domain.com/project_name/trunk

shows all the log messages. Note this did not show all the 10 revisions that I had on my local repository. It showed only the changes that I had made after the migration. So the local repository version was at 10 but the remote repository was moving from version 3.

Debugging Rails App in Realtime with the breakpointer

1) include the line: breakpoint "some description goes here" where you want the program execution to stop.
2) From the rails app root directory run: script/breakpointer
3) Fire the browser and let the app hit the breakpoint, you will be taken to the >> prompt where you can examine variables.

This helped me to customize the Attachment_fu plugin so that image upload is optional.

Saturday, June 23, 2007

Testing XML output in Rails

1. get :action_name, :format => "xml", :id => 1
2. content = @response.body
3. assert_select "title", :text => "Rails Recipes"

The above steps basically simulate http://localhost:3000/xmlcontroller/action_name/1.xml.

Let's say you have multiple records in the xml output you can check:

assert_select "book", :count => 2

In this case there will be two books in xml output.

Thursday, June 21, 2007

.svn: Commit failed

Error:
.svn: Commit failed (details follow):
svn: Out of date: 'vendor/plugins' in transaction '7-1'
svn: Your commit message was left in a temporary file:
svn: '/Users/myprojects/svn-commit.tmp'

svn up first and then svn delete on the files that is no longer required and then commit.

Send Method in Ruby

When you have an object, you can set the values for its attributes by:

obj.send(#{attribute}, value) where attribute is the actual attribute while looping through an array of strings that contains the attribute names. The value is the actual value that is used to initialize the attribute.

Wednesday, June 20, 2007

Recursion in Ruby

Calculate x to the power of y using recursion.

def test(x, y)
if (y == 0)
return 1
else
test(x, y-1) * x
end
end

puts test(2,3)

This was a interesting question during the interview. I never understood recursion. The interviewer skillfully provided some clues for me to figure this one out myself. I wrote down some sample values for x and y in a tabular format. Worked through the problem and surprisingly come up with the right answer!

Tuesday, June 19, 2007

No such file or directory - /tmp/501/nl.uu.phil.SSHAgent.socket (Errno::ENOENT)

I was hacking with passwordless ssh login when Capistrano deployment failed with that message. Running (on Mac OS):

$ ssh-agent bash
$ ssh-add

and then running cap tasks fixed the problem for now.

Monday, June 18, 2007

Using acts_as_reportable Rails plugin to generate CSV data from Active Record

1) sudo gem install ruport -y
2) require "ruport" in environment.rb
3) include acts_as_reportable in your model.

You are now ready to play with the model in the script/console. Very easy and powerful plugin. For more info, check out http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/AARTutorial

Upgraded Ruby to Ruby 1.8.6-p36

This version is compatible with FasterCSV. Hivelogic instructions will work, but you need to use the the url ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p36.tar.gz
to install the latest Ruby distribution. This release was announced on Ruby-Talk mailing list.

You can skip the readline installation if you have it already installed for Ruby 1.8.6 released on march 07.

4 Useful Rails Plugins

PDF Plugin
Calendar Helper Plugin:
Active Record Extensions:
Acts As Reportable

Sunday, June 17, 2007

Pending Deployment Tasks

1) Find out how deploy_with_migrations Capistrano switch works.
2) Change the style.css for the site.
3) How to connect to the database during deployment without using database.yml?
4) How to upgrade if you freeze gems?

This is answered in Rails Recipes. 5) Install Exception Notification plugin and SiteMeter.
6) Contact model, create a secure RSS feed. Refer Rails Recipes.

Deployed Rails App on Staging and Production Environments

1) I looked at the mongrel.log file, the error message said that it
could not find staging.rb. So I created an empty staging.rb file under
config/environments directory.

2) staging configuration for socket value was set to the output of
locate mysql.sock.

3) The staging.log showed that require 'turn' statement in
environment.rb was missing the turn gem. I moved this statement to
development.rb, since it is required only for development.

Missing gem headaches: I also learned about rake freeze gem that allows
taking gems to the deployment environment. But I don't know if I freeze
a gem I will be able to upgrade it later. I will get this clarified from
Rails mailing list.

My emails are being sent, but when I signup I see the link as:

http://localhost.localdomain/activate/7fb260146d37cf5aec957fa0662d94c52a9f2488

http://#{ActionMailer::Base.smtp_settings[:domain]}/activate/#{user.activation_code} line in the rhtml template takes the smtp_settings defined for that environment. So
define the domain in staging.rb to fix this problem

Saturday, June 16, 2007

`No such file or directory – /tmp/mysql.sock`

run `locate mysql.sock` or `locate mysqld.sock` to find where your socket is located, then update database.yml to reflect your system’s configuration. So your entry will be:

socket: /path/to/mysql.sock

Friday, June 15, 2007

Simply Rich Association Plugin Released

I am excited to make my first plugin available for public. You can
checkout the code by doing:

svn checkout http://simply-rich-association.googlecode.com/svn/trunk/
simply-rich-association



Hosted on Google Code: Project home page is http://code.google.com/p/simply-rich-association/

The README file has good explanation of what the plugin can do. http://simply-rich-association.googlecode.com/svn/trunk/README
Enjoy!

Wednesday, June 13, 2007

Komodo IDE 4.1 First Impression

When you run the Komodo it loads all the code intelligence for PHP, Python etc. Very annoying when you want to just work on Ruby. After installation the tutorial instructions tell you to load a certain file. Uhh? Where did it install? It does not know where it installed so you have to manually search to load the tutorial.

There is no way to customize the appearance, no themes. No thanks, I will stick with Textmate for now. Maybe Netbeans might be a good alternative one day.

How to convert a name of a class to Class in Ruby

"Foo".constantize will return Foo. Now you can call any methods on Foo.

Attachment_fu - How to display the image

Mike clark's weblog has a good article on how to use attachment_fu to upload images. In my application I did not need any thumbnails. In this case to display the image in the show.rhtml I had to use the image_tag(@person.public_filename) to display the image.

Adding multiple files to Subversion at once

svn st | grep "^?" | awk '{ print $2}' | while read f; do svn add $f; done

If you want all the ? files to be added. Found this tip here http://www.gregwhitescarver.com/blog/2006/05/22/add-multiple-files-in-subversion-at-once/

Creating admin accounts using Rake task

Memphisto project by Rick Olson has a Rake task called db:bootstrap that is in bootstrap.rake file. It creates admin accounts from the data specified in the users.yml file. Awesome!!!

How to export data from one database and import into another.

mysqldump -u root -p myapp_staging some_table > mytable.sql

and then

mysql -u root -p myapp_acceptance < mytable.sql

Rails Refactoring to Resources - Using CRUD and REST in Your Rails Application

Nice book from Apress written by Trotter Cashion. I finished reading this book last night. It has a very good coverage of the RESTful goodness in Rails. Short and sweet. Learned a lot from this book. Very well written. I give it 4.5 out of 5 stars. The reason is ActiveResource in the latest Rails is not discussed in the book.

Saturday, June 09, 2007

svn: Out of date: '/trunk' in transaction '2-1

When I commit the changes to the svn, I got:
svn ci .
Sending .
svn: Commit failed (details follow):
svn: Out of date: '/trunk' in transaction '2-1'
svn: Your commit message was left in a temporary file:
svn: '/Users/balaparanj/work/zepho/ard/svn-commit.tmp'

Out of date here means the repository version is not the same as the local version. It works after doing svn up.

Tuesday, May 15, 2007

Rails Performance Screencast notes

Here is the notes I took notes from topfunky's httperf screencast.

Production Log Analyzer is a gem that lets you find out which pages on
your site are dragging you down.

Change one thing at a time and benchmark. Take actual data from
production db, export it and use it for benchmarking. Create a
separate environment for benchmarking.

Install httperf. Need 2 machines one for running httperf client and
the other for running Rails app.

Shut down all unnecessary programs on both machines to reduce CPU
usage. This reduces unpredictable results.

Process for Benchmarking Webapplication using Httperf

1) rake sweep_cache
2) mongrel_rails start -e production (no logging)
3) Hit a particular page once
4) run httperf (with consistent args)

Step 1 and 2 is run on Rails app machine. Go to browser on the client
machine load the page and run:

httperf --server machine_name --port 3000 --ur /page_name --num-conns 1000

The number of connections parameter can be changed. In the output of
the httperf make sure that you get number of replies is same as total
connections. Reply status should not have any errors. If there are any
httperf errors the results must be tossed out.

Copy the "Reply rate" line of the httperf output for different number
of connections and use topfunky's script to generate graphs.

./script/parse_httperf_log log/httperf-sample-log.txt

Tuning Mongrel for Performance

Here are the steps for finding how many requests per second a single
Mongrel process can handle.

httperf --server machine_name --uri /page_name --port 3000 --num-conns
7000 --rate 650 --hog

650 is the requests/sec

If this process hangs for more than 20 secs then we have overloaded
Mongrel. Httperf should have no errors (because it means httperf was
overloaded, in that case data must be tossed out).

Try different values for number of connections and rate, such as 6600,
660, 6700, 670 etc. Till the reply rate reaches a maxium and begins to
drop off.

Scaling Rails - Notes from Silicon Valley Ruby on Rails Meetup

Some websites are launched by getting it on TechCrunch, Digg, Reddit
etc. In such cases there is no time to grow organically.

Resources:

1. The Adventures of Scaling Rails -
http://poocs.net/2006/3/13/the­adventures­of ­scaling­stage­1
2. Stephen Kaes "Performance Rails" - http://railsexpress.de/blog/f
iles/slides/rubyenrails2006.pdf
3. RobotCoop blog and gems -
http://www.robotcoop.com/articles/2006/10/10/the­sof
tware­and­hardware­that­runs­our­sites
4. OReilly's book "High Performance MySQL

This presentation's focus is on what's different from previous
writings. For comprehensive overview refer the above resources.

Scribd.com was in launched in march, 07. It is the "YouTube" for
documents and it handles around 1 Million requests per day.

Current Scribd Architecture

1 Web Server
3 Database Servers
3 Document Conversion Servers
Test and Backup machines
Amazon S3

Server Hardware

Dual, dual core woodcrests at 3 Gz
16 GB of memory
4 15K SCSCI hard drives in a RAID 10
Disk speed is important. Don't skimp; you're not Google, and it's
easier to scale up than out.
Hosted by Softlayer.

Software

CentOS
Apache/Mongrel
Memcached, RobotCoop's memcache-client
Stefan Kaes' SQLSessionStore - This is the best way to store peristent sessions.
Monit, Capistrano
Postfix

They ran tests and found out that fragment caching improved
performance for their web app.

How to Use Fragment Caching

Consider only the most frequently accessed pages.
Look for pieces of the page that don't change on every page view and
are expensive to compute

Just wrap them in a
<% cache('keyname') do %>
...
<% end %>
Do timing test before and afterwards; backtrack
unless significant performance gains

Expiring fragments - 1. Time based

Use memcached for storing fragments
It gives better performance
It is easier to scale to multiple servers
Most importantly: It allows time­based expiration

Use plugin http://agilewebdevelopment.com/plugins/memcache_fragments_with_time_e...
Dead easy:
<% cache 'keyname', :expire => 10.minutes do %>
...
<% end %>

Expiring fragments - 2. Manually

No need to serve stale data
Just use: Cache.delete("fragment:/partials/whatever")
Clear fragments whenever data changes
Again, easier with memcached

They also discussed about how to use 2 database servers with Rails
app. For more information you can see the slides at
http://www.scribd.com/doc/49575/Scaling-Rails-Presentation

Q & A

They use SWF open source plugin for uploading documents (it allows
multiple docs to be uploaded simultaneously)

They pay only $100 monthly for Amazon S3 for 5 tera bytes of b/w
usage. Downside of using Amazon S3 is that they cannot generate
analytics for that part of the app.

The uploaded files goes to a queue and is processed in the background.
So the documents don't appear immediately on the site if the load is
high.

Tip from the first presentation on CacheBoard: It uses backgroun drb
plugin by Ezra for exporting documents in XML format.

Tuesday, May 01, 2007

Configuring Selenium to Run Automated Tests

Had to dig out this buried info on Selenium to get the browser to run the automated tests.

Also the Selenium tests are not independent of each other. The tests within a particular file depend on what page the previous test has ended. Strange but if you don't know this you will end up spending lot of time banging your head against the wall.

Colorizing ZenTest output

To get the green and red color for autotest:

1. sudo gem install --remote Redgreen
2. put the statement: require 'redgreen' in the environment.rb

restart the autotest if is already running. Now you will have green color for passing scenario and red for failing tests. Enjoy!

Monday, April 30, 2007

Tests : Before

21:32:17:~/clients/brep/td/trunk > rake stats
(in /Users/balaparanj/clients/brep/td/trunk)
/Users/balaparanj/clients/brep/td/trunk/config/boot.rb:38:Warning: require_gem is obsolete. Use gem instead.
+----------------------+-------+-------+---------+---------+-----+-------+
| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers | 1158 | 972 | 28 | 118 | 4 | 6 |
| Helpers | 329 | 283 | 0 | 42 | 0 | 4 |
| Models | 975 | 759 | 25 | 127 | 5 | 3 |
| Libraries | 733 | 552 | 9 | 82 | 9 | 4 |
| Components | 0 | 0 | 0 | 0 | 0 | 0 |
| Integration tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Functional tests | 701 | 522 | 52 | 106 | 2 | 2 |
| Unit tests | 493 | 382 | 26 | 62 | 2 | 4 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total | 4389 | 3470 | 140 | 537 | 3 | 4 |
+----------------------+-------+-------+---------+---------+-----+-------+
Code LOC: 2566 Test LOC: 904 Code to Test Ratio: 1:0.4

ssh: somedomain.org: No address associated with nodename

This error message happened while remote login using ssh. ping command did not work. The problem was the domain was incorrect.

Saturday, April 28, 2007

Ruby: No such file to load -- ubygems (LoadError)

I deleted the contents of directory site_ruby and I was getting that error message. After some googling found Rich Kilmer's reply

"You have installed rubygems and set the RUBYOPT variable. This is the
downside to using the RUBYOPT :-(

Just unset that variable and then you should be good to go."

-rich

Thanks Rich, that fixed my problem.

rmagick headache on mac os

Finally resolved the rmagick installation problems. The actual problem was not rmagick itself but a custom script in my project.

I found the RMagick install script for Mac OS X - Version 0.2.0
on rmagick installation faq.

/opt/local/bin/ruby: bad interpreter:

I was getting the weird ruby bad interpreter error message after I deleted everything under site_ruby directory. I was working on getting the rmagick working on my laptop. I resolved the problem by reinstalling the Ruby 1.8.6 and Rubygems 0.9.2.

Friday, April 27, 2007

warning: multiple values for a block parameter (0 for 1)

In the following irb session the error message indicates that the input parameter is missing.

>> hello = lambda { "hello" }
=> #
>> hello.call
=> "hello"
>> log = lambda { |str| puts "[LOG] #{str}" }
=> #
>> log.call
(irb):16: warning: multiple values for a block parameter (0 for 1)
from (irb):17
[LOG]
=> nil
>> log.call("A test log message")
[LOG] A test log message
=> nil

Friday, April 20, 2007

Capistrano Concepts

Chris Selmer's Capistrano Presentation from the April 5, 2007 DCRUG
meeting is very good.

The Rails Edge conference had discussion on the material
covered in this presentation, but this presentation connected all the
dots for me.

Copying to the clipboard in UNIX

You can send any output to the clipboard by using pbcopy. For example: history | pbcopy will send the output of history command to the clipboard. You can just paste it in email or other document. Very nice. pbpaste will paste the contents of the clip board.

Tuesday, March 20, 2007

How to create drop down boxes in Ruby on Rails

Migration file : 001_create_people.rb

class CreatePeople < ActiveRecord::Migration
def self.up
create_table :people do |t|
t.column :first_name, :string
t.column :last_name, :string
t.column :email, :string
t.column :created_at, :datetime
end
end

def self.down
drop_table :people
end
end

person.rb
class Person < ActiveRecord::Base
has_many :tasks
end

task.rb
class Task < ActiveRecord::Base
belongs_to :user

def self.find_all_person
Person.find(:all, :order => "first_name").map {|u| [u.first_name, u.id] }
end

end

tasks/_form.rhtml

<h2> Create a Task for a Person</h2>
<% form_for ( :task, :url => path, :html => { :method => method } ) do |f| %>
    <p>
    
Title:        <br>
        <%= f.text_field :title, :class => 'text_field' %><br>
    </p>
    <p>
    
Content:
        <br>
        <%= f.text_field :content, :class => 'text_field' %><br>
    </p>

        <br>
        
        <p>Select a priority:
    
          <%= f.select ( :priority, %w { 1 2 3 4 5 6 7 8 9 10 } ) %>
    
        </p>
    </p>

    Person:
            <br>
            <%=
             f.select ( :people_id, @people )
            %>

        </p>
    
    <p>
        <%= submit_tag button_text %>
    </p>

<% end %>

tasks/edit.rhtml
<h1>Editing task</h1>

<%= error_messages_for :task %>

<% form_for ( :task, :url => task_path ( @task ) , :html => { :method => :put } ) do |f| %>
  <p>
    <%= submit_tag "Update" %>
  </p>
<% end %>

<%= link_to 'Show', task_path ( @task ) %> |
<%= link_to 'Back', tasks_path %>

tasks/index.rhtml
<h1>Listing tasks</h1>

<table>
  <tr>
  </tr>
  
<% for task in @tasks %>

<tr>
    <td><%= link_to   ( h task.title ) ,    task_path ( task ) %></td>
  </tr>

<% end %>
</table>

<br />

<%= link_to 'New task', new_task_path %>

tasks/new.rhtml
<h1>New task</h1>

<%= error_messages_for :task %>

<%= render :partial => 'form', :locals => { :path => tasks_path,
                                              :method => :post,
                                              :button_text => 'Create' } %>
                                            

<%= link_to 'Back', tasks_path %>

tasks/show.rhtml

<h2>Task </h2>
    <p> Title: <%=  h @task.title %></p>
    <p>Content: <%= h @task.content %></p>
    <p>Priority: <%= h @task.priority %></p>
    <p>Created At: <%= @task.created_at %></p>
    <p>Person: <%=  @person.first_name %></p> -->
    
<%= link_to 'Back', tasks_path %>

people/_form.rhtml

<% form_for ( :person, :url => path, :html => { :method => method } ) do |f| %>
    <p>
    
    <strong>First Name: </strong>
        <br>
        <%= f.text_field :first_name, :class => 'text_field' %><br>
    </p>
    <p>
    
    <strong>Last Name: </strong>
        <br>
        <%= f.text_field :last_name, :class => 'text_field' %><br>
    </p>

    <strong>Email: </strong>
        <br>
        <%= f.text_field :email, :class => 'text_field' %><br>
    </p>

    <p>
        <%= submit_tag button_text %>
    </p>

<% end %>

people/edit.rhtml
<h1>Editing person</h1>

<%= error_messages_for :person %>

<%= render :partial => 'form', :locals => { :path => person_path ( @person ) ,
                                            :method => :put,
                                            :button_text => 'Update' }
%>


<%= link_to 'Show', person_path ( @person ) %> |
<%= link_to 'Back', people_path %>

people/index.rhtml
<h1>Listing people</h1>
* Create an application to track a person's tasks. The user should be able to
create people, create tasks, and assign a task to a person when the task is created.

<table>
  <tr>
  </tr>
  
<% for person in @people %>
<tr>
    <td><%= link_to   ( h person.first_name ) ,    person_path ( person ) %></td>
  </tr>
  
<% end %>
</table>

<br />

<%= link_to 'New person', new_person_path %>

people/new.rhtml
<h1>New person</h1>

<%= error_messages_for :person %>

<%= render :partial => 'form', :locals => { :path => people_path,
                                              :method => :post,
                                              :button_text => 'Create' } %>


<%= link_to 'Back', people_path %>

people/show.rhtml

<h2>Person </h2>
    <p>First Name: <%=  h @person.first_name %></p>
    <p>Last Name: <%= h @person.last_name %></p>
    <p>Last Name: <%= h @person.email %></p>

<%= link_to 'Edit', edit_person_path ( @person ) %> |
<%= link_to 'Back', people_path %>

home/index.rhtml
<%= link_to  "People",    :controller => :people, :action => :index %><br>
<%= link_to  "Tasks",    :controller => :tasks, :action => :index %>

layouts/people.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>People: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
</head>
<body>

<p style="color: green"><%= flash[:notice] %></p>

<%= yield  %>

</body>
</html>

layouts/tasks.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Tasks: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
</head>
<body>

<p style="color: green"><%= flash[:notice] %></p>

<%= yield  %>

</body>
</html>

controllers/home_controller.rb
class HomeController < ApplicationController
def index

end
end

people_controller.rb
class PeopleController < ApplicationController
# GET /people
# GET /people.xml
def index
@people = Person.find(:all)

respond_to do |format|
format.html # index.rhtml
format.xml { render :xml => @people.to_xml }
end
end

# GET /people/1
# GET /people/1.xml
def show
@person = Person.find(params[:id])

respond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @person.to_xml }
end
end

# GET /people/new
def new
@person = Person.new
end

# GET /people/1;edit
def edit
@person = Person.find(params[:id])
end

# POST /people
# POST /people.xml
def create
@person = Person.new(params[:person])

respond_to do |format|
if @person.save
flash[:notice] = 'Person was successfully created.'
format.html { redirect_to person_url(@person) }
format.xml { head :created, :location => person_url(@person) }
else
format.html { render :action => "new" }
format.xml { render :xml => @person.errors.to_xml }
end
end
end

# PUT /people/1
# PUT /people/1.xml
def update
@person = Person.find(params[:id])

respond_to do |format|
if @person.update_attributes(params[:person])
flash[:notice] = 'Person was successfully updated.'
format.html { redirect_to person_url(@person) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @person.errors.to_xml }
end
end
end

# DELETE /people/1
# DELETE /people/1.xml
def destroy
@person = Person.find(params[:id])
@person.destroy

respond_to do |format|
format.html { redirect_to people_url }
format.xml { head :ok }
end
end
end

controllers/tasks_controller.rb
class TasksController < ApplicationController
# GET /tasks
# GET /tasks.xml
def index
@tasks = Task.find(:all)

respond_to do |format|
format.html # index.rhtml
format.xml { render :xml => @tasks.to_xml }
end
end

# GET /tasks/1
# GET /tasks/1.xml
def show
@task = Task.find(params[:id])
@person = Person.find(:first, :conditions => "id = #{@task.people_id}")

respond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @task.to_xml }
end
end

# GET /tasks/new
def new
@task = Task.new
@people = Task.find_all_person
end

# GET /tasks/1;edit
def edit
@task = Task.find(params[:id])
end

# POST /tasks
# POST /tasks.xml
def create
@task = Task.new(params[:task])
@person = Person.find(:first, :conditions => "id = #{@task.people_id}")

respond_to do |format|
if @task.save
flash[:notice] = 'Task was successfully created.'
format.html { redirect_to task_url(@task) }
format.xml { head :created, :location => task_url(@task) }
else
format.html { render :action => "new" }
format.xml { render :xml => @task.errors.to_xml }
end
end
end

# PUT /tasks/1
# PUT /tasks/1.xml
def update
@task = Task.find(params[:id])

respond_to do |format|
if @task.update_attributes(params[:task])
flash[:notice] = 'Task was successfully updated.'
format.html { redirect_to task_url(@task) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @task.errors.to_xml }
end
end
end

# DELETE /tasks/1
# DELETE /tasks/1.xml
def destroy
@task = Task.find(params[:id])
@task.destroy

respond_to do |format|
format.html { redirect_to tasks_url }
format.xml { head :ok }
end
end
end

Monday, March 05, 2007

sudo: port: command not found

export PATH=$PATH:/opt/local/bin
export MANPATH=$MANPATH:/opt/local/share/man
export INFOPATH=$INFOPATH:/opt/local/share/info

Included the above lines in .bash_profile (my mac is using bash shell) and voila a nagging problem sudo: port: command not found is gone!!!

sudo port -d selfupdate

ran successfully. Now I was able to install FreeImage by running:
sudo port install freeimage

Thursday, March 01, 2007

LoadError: no such file to load — selenium

LoadError: no such file to load — selenium. This kind of error message can happen if you have installed anything as a gem but you have not specified require "rubygems" as the first statement in your program.

Wednesday, February 28, 2007

LoadError: no such file to load — flexmock

If you get this error, it means you need the statement: require 'rubygems' as the first line in your program.

Monday, February 05, 2007

Subversion 1.4.3 upgrade

Installed the latest version of Subversion. I had the older version 1.3, it looks like it installed successfully. svn --version shows the version as 1.4.3 and the files which were already in svn is still there.

Sunday, February 04, 2007

Spam Prevention using the Obfuscator Widget for Mac OS

This plugin obfuscates your email so that spambots cannot recognize the email that you post on your web page.

Testing... my email is : bparanj@gmail.com

CSS Tweak - Nice Widget for Mac OS to optimize CSS

CSS Tweak! widget is very useful plugin to optimize your CSS files. Just select the file you want to optimize from the Finder, hit F12 and drop it into the widget, select the options and the rest is done by the widget! Very cool.

Code to HTML Mac OS widget test - Download Code2HTML

#!/bin/sh
pid=$ ( ps -o pid, command | grep '\<script/server\>' | awk ' { print $1 } ' )
kill -9 $pid
ruby script/server

Code2HTML is a nifty little plugin that helps to convert the code to html. It solved my problem of posting code to the blog without messing up the characters. It is very quick and easy to convert the code to html.

Tuesday, January 23, 2007

Colorizing Autotest

1. install turn and facets
2. require 'turn' in environment.rb in the Rails project.

Step 2 must be done for each project that needs the colorizing of the autotest window. Another way to do this is shown in one of the topfunky's videos.

Friday, January 19, 2007

The new :& syntax in Ruby

The advantage of the new syntax is that it allows passing in a proc object, which is powerful.

I am surprised how the presenter in the No Fluff Just Stuff thought its main purpose was to make the code concise!

Thursday, December 14, 2006

Functional Testing in Rails that Requires Login

For RESTful authentication, there is a
login_as(user) method in AuthenticatedTestHelper module that sets the
current user
in the session from the user fixtures. This is under the lib directory.

In my functional test, I have:

def test_should_show_billing_profile_for_valid_login
login_as (:aaron)
get :show, :id => :aaron.id
assert_response :success
assert_select "html:root>head>title", "BillingProfiles: show"
end

users.yml looks like this:

quentin:
id: 1
login: quentin
email: quentin@example.com
salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
created_at: <%= 5.days.ago.to_s :db %>
aaron:
id: 2
login: aaron
email: aaron@example.com
salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
created_at: <%= 1.days.ago.to_s :db %>


class BillingProfilesController < ApplicationController

before_filter :login_required

def show
@user = User.find(session[:user], :include => [:billing_profile])
@billing_profile = @user.billing_profile

respond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @billing_profile.to_xml }
end
end

The problem was that I was using session[:user_id] in my controller
whereas the RESTful authentication
module is using session[:user] as shown below:

module AuthenticatedTestHelper
# Sets the current user in the session from the user fixtures.
def login_as(user)
@request.session[:user] = user ? users(user).id : nil
end
....

So I changed my controller code to use session[:user] and my tests now
pass! The plugin itself has the API to help you do the functional
testing. Very nice indeed.

Monday, December 04, 2006

Installing Sqlite3 on Mac OS 10.4

1. Install DarwinPorts, download DarwinPorts 1.3.2-archive.tar.gz, unzip it.
2. Copy unzipped folder to some location
3. cd to that location cd darwinports/base and run ./configure
4. make
5. sudo make install
6. Add export PATH=$PATH:/opt/local/bin to ~/.profile
7. Either logout of Mac or do source .profile
8. Run port sync
9. sudo port install rb-sqlite3
10.Run sqlite databasename in a shell. You will go to the sqlite command prompt.

You can now create tables and run sql queries. The advantage of this database is that it speeds up the testing during development. It is very fast.

Rails Cheat Sheets

1. Assert Select CheatSheet
2. Ruby on Rails CheatSheet
3. Textmate Rails CheatSheet
4. Scriptaculous CheatSheet
5. RJS Demystified
6. Form Helpers CheatSheet
7. Active Record Relationships CheatSheet
8. AJAX CheatSheet
9. Ruby on Rails Testing CheatSheet
10. TextMate CheatSheet for Rails Developers

Wednesday, November 29, 2006

Email validation plugin

1.Setup the Rails project in Subversion by following the Subversion Primer for Rails blog post.
2. Ran into problems while installing plugins and after reading the James Adams's plugin book, I found the solution, I had to do:

script/plugin install –o https://svn.greenpeace.org/repositories/rails_plugins/validates_as_email/tags/0.1.4

to install the plugin.

I also looked at the test directory of the plugin and did the same assert in my unit test.

Tuesday, November 21, 2006

Restarting WEBrick using script

#!/bin/sh
pid=$(ps -o pid,command | grep '\' | awk '{print $1}')
kill -9 $pid
ruby script/server

This script restarts the Webrick cleanly (doing CTRL+c does not seem to shutdown the server)

Save it in a file, restart.sh. Do a chmod +x restart.sh and type the command: sh restart.sh to run it.

Thursday, November 09, 2006

Rake Aborted! Migration Headache

If the migration is not working in AWDWR Rails examples. Remember that you must be on Edge Rails to make it work.

The Ruby Way, Ruby in a Nutshell and Rails Plugin Extending Rails Beyond the Core

The Ruby Way and Ruby in a Nutshell books arrived from Amazon today. I will post the review when I get a chance.

I also bought the "short cut" Rails Plugins by Addison Wesley, a 100 page pdf book. This book is a gem. More to come soon...

Ruby Interceptor

Beyond Java book had a good example of Interceptor in Ruby. It is like AOP, but is simpler.

1. Create an alias for the method that you want to intercept.
2. Define a new method with the same name as the old method
3. Delegate the call to the old method and add new code to do whatever you want in this method.

You basically open the class, intercept the calls to that method and add additional functionality to the method.

Tuesday, November 07, 2006

Head Rush AJAX

Very good book. Shows the big picture in a very easy to understand way. The concepts are well explained and brings any novice up to speed quickly. This book helped me to move on to study other materials like RJS Templates by OReilly.

Metaprogramming with Ruby

Ruby is a dynamic language. You can create classes and methods at runtime. This is metaprogramming. You can write code that writes code.

Example: Data format driving the code, CSV file with header at the top.

file: people.txt
----------------
name,age,weight,height
"Smith, John", 35, 175, "5'10"
"Ford, Anne", 49, 142, "5'4"
"Taylor, Burt", 55, 173, "5'10"
"Zubrin, Candace", 23, 133, "5'6"

Requirements:
1. The code must not change when a new attribute is added to the existing file or if we are given a different file with different attribute names.
2. The header values such as name and age must be treated as attribute names.

Create a class with a name derived from the file name. First line of the file must have list of attribute names. Checks that can added are: Check the attribute name is a legal Ruby method name, badly formed and missing data.

Given the file name we can create a class from its contents. So:

class_name = File.basename(file_name,".txt").capitalize # Create the class name
# e.g. "foo.txt" => "Foo"
klass = Object.const_set(class_name,Class.new)

Monday, November 06, 2006

Greasemonkey

Awesome Firefox extension, install the plugin and browse the scripts. I installed a script that blocks all Yahoo ads. No more annoying flashing ads in my email account. There are tons of useful scripts. One of the script I installed compares the price of Amazon books with other online stores.

Also, install the scripts one at a time. Install a script and use your browser for sometime and see if everything is fine. This is important because I installed lot of scripts on my laptop and now one of the script is opening up all the links in a new window!

If you install it one at a time, you can easily find out which script is causing the problem.

Metaprogramming - Write code that generates code

Uses

1. Open-Closed principle - Programs that need to pre-generate data tables
2. Mini-language to handle boilerplate code - Programs that have a lot of boilerplate code that cannot be abstracted into functions
3. Programs using techniques that are overly verbose in the language you are writing them in

The art of metaprogramming, Part 1: Introduction to metaprogramming - Jonathan Bartlett

Excellent article on Metaprogramming with Ruby

Sunday, November 05, 2006

How to load fixtures after tables and indexes are created.

Steve Hammond's Blog had this interesting tip:

Can we tell a migration to load the fixtures after it has created the tables and indexes?

Fixtures.create_fixtures('test/fixtures', %w{archetypes tile_types tiles})

The first argument is the directory where the fixtures can be found and the second is an array of fixtures to be loaded. This will load the fixtures into the environment where the fixture is being run. As usual Rails will figure out YAML vs. csv fixtures for you

Thursday, November 02, 2006

Using the Ruby Development Tools plug-in for Eclipse

This plugin allows debugging, check it out.

Resources - Domain Specific Languages in Ruby

1. Seeing MetaClasses Clearly

2. MetaprogrammingWriterTopia by Bill Katz

3. Domain Languages as Rails Plug-Ins: Steve Hammond

4. Meta Rails - Stuart Halloway

5. Neal Ford - Language Oriented Programming Keynote

Script to Setup Rails in Subversion

The following notes is based on the thread Create a rails project skeleton and import and checkout from svn all at once!

1. Create your repository on the server

2. Put the source code in a file called ‘svnrails’ inside of a directory that’s in $PATH. I have mine in /usr/local/bin (where the svn, rails and ruby binaries like to do their thing)

3. This will work with any kind of svn repository (ie. file:///, svn://, http://)

4. If your repository requires authorization, you will be prompted when necessary.

5. I haven’t built any error handling into this, so use the ol’ “measure twice and cut once” technique when typing this command

6. Type the command without arguments for usage

7. You have the option of not creating the /trunk, etc. directories in the repository; and the default command looks like this:

svnrails myapp svn://myserver

8. As long as you’ve created a repository called myapp on the subversion server, this script will automatically import your project into it. In other words, it defaults the name of the repository to be the same as the name of the app; this can be overriden (sensible defaults and all that).

9. Ignores various files in the repository as per the rails wiki

You can find the code here


Doubt: Does this require any changes for Edge Rails?

Wednesday, November 01, 2006

ZenTest Notes

To use unit_diff, pipe normal tests through it:

$ ruby ./TestZenTest.rb | unit_diff

Auto-test:

pressing Ctrl-c once reruns the tests immediately. Pressing the key combination twice terminates autotest.

$ autotest -help

options:

-v Be verbose.
Prints files that autotest doesn't know how to map to tests.

-rails Force rails mode.
Rails will be automatically detected by the presence of config/environment.rb. Use this if you don't have one.

You may need to run 'rake db:test:prepare' before
starting autotest on a rails project.

-vcs=NAME Version control system to update.
Autotest will automatically update every vcstime
seconds.
Autotest understands Perforce (p4), CVS (cvs) and
Subversion (svn).

-vcstime=N Update source control every N seconds.
Defaults to every five minutes (300 seconds).

ZenTest MyProject.rb TestMyProject.rb > missing.rb

./TestMyProject.rb | unit_diff

autotest

multiruby ./TestMyProject.rb

(and other stuff for Test::Rails)

How to use ZenTest on Rails?

ZenTest Documentation

Resources for Testing Ruby on Rails

1. A Guide to Testing the Rails
2. Test First Programming with Ruby
3. Ruby on Rails Testing Cheat Sheet
4. Testing Rails Apps - Mike Clark
5. Test Your Helpers
6. Testing Rails controllers communicating with external web services
7. Test Driven Designg Using ZenTest
8. A Rails Testing Tutorial
9. How to Use ZenTest with Ruby
10. Autotest Rails
11. Testing Rails Apps
12. Selenium on Rails
13. Running Your Rails App Headless
14. YAML Fixtures
15. Testing RJS Templates
16. RJS Assertions
17. 2005 Rubyconf ZenTest Movies - Ryan Davis
18. ZenTest Blog
19. Test-First development

Tuesday, October 31, 2006

Collecting email addesses on your website

In email marketing it is important to use the names of your subscribers to establish connection. When users fillout the forms to subscribe to your list some of them will be lazy and enter names in all lowercase. When you merge the fields during mailing your newsletter it can be very tedious to clean up the database.

In Rails, you can cleanup the name fields as follows:

test = "StRrIPPed TEst"
test.upcase.titlecase

This will create a string : "Strripped Test"

Remember that Rails has opened the existing string class and added these methods to it. So to find out the methods that are available:

~/work/testr > ./script/console
(From the Rails project directory)

> test.methods

will give you list of all available methods.

Subversion Setup for Edge Rails

The following steps are customized for my needs from the Subversion Primer for Rails Project.

1. mkdir ~/svn

2. svnadmin create --fs-type=fsfs ~/svn/pinkatio

pinkatio is the name of the Rails project

3. REPOS=file:///Users/balaparanj/svn/pinkatio

For some reason the `pwd' embedded inside the file:// does not work.

4. svn mkdir --message="Initial project layout" $REPOS/trunk $REPOS/tags $REPOS/branches

5. ~/work/pinkatio > rails pinkatio

6. ~/work/pinkatio > svn checkout $REPOS/trunk .

7. ~/work/pinkatio > svn add --force .

8. ~/work/pinkatio > svn mkdir db/migrate tmp

Ignore any error message for tmp directory.

9. ~/work/pinkatio > svn revert log/*

10. ~/work/pinkatio > svn propset svn:ignore "*.log" log

11. ~/work/pinkatio > svn propset svn:ignore "*" tmp

12. ~/work/pinkatio > svn propset svn:ignore "*doc" doc

13. ~/work/pinkatio > svn propset svn:executable "*" `find script -type f | grep -v '.svn'` public/dispatch.*

14. ~/work/pinkatio > svn commit --message="New Rails project"

15. ~/work/pinkatio > svn propset svn:externals "rails http://dev.rubyonrails.org/svn/rails/trunk/" vendor

16. ~/work/pinkatio > svn update vendor

17. ~/work/pinkatio > yes | rails .

18. ~/work/pinkatio > svn commit --message="Living on the Edge - set svn:externals on vendor / for Rails"


I skipped the steps to delete and remove the index.html from svn because the command yes | rails . undoes that step.

Resources:

1. How to use Rails with Subversion
2. Create a Rails project skeleton and import and checkout from SVN all at once!

Rubyisms in Rails Book Review

I just finished reading this book. This book has the best explanation on symbols. It does a good job of explaining duck typing, blocks and metaprogramming. The topics under metaprogramming are very easy to understand, they are reflection, message sending and method missing.

I found it easier to understand because it shows snippets of Java code to show how the problem can be solved and then gives the Ruby equivalent.

It does not explain very well or go deeper on the DSL topic. This could have doubled the size of the book easily.

Thursday, October 26, 2006

Rails Secure Plugin and Google Checkout Plugin for Rails

secure_action is a ruby on rails plugin which makes it easy to defend your site against assumed logged in attacks.

To install, check out the code in your RAILS_ROOT/vendor/plugins/ directory and follow the instructions in the README:

svn checkout http://secure-action-plugin.googlecode.com/svn/trunk/ secure-action-plugin

Interesting article from a developer

http://code.google.com/apis/checkout/cookbook.html

svn checkout http://checkout-on-rails.googlecode.com/svn/trunk/ checkout-on-rails

Rails RESTful Authentication Plugin Part II

1. Include the line: map.connect '/', :controller => "sessions", :action => 'index'
in routes.rb
Browse the source code you will see that after login and logout the action methods route to '/', so the above definition will load the index.rhtml for the sessions_controller

2. In the sessions_controller.rb add the following method:
def index
end
3. Create a index.rhtml file in the views/sessions directory, include the following lines in the file:

<% if flash[:notice] -%>
<%= flash[:notice] %>

<% end -%>

Now when you login or logout, you will the message "You are logged in" and "You have been logged out message".

4. You can also uncomment the code for remember me functionality in the rhtml file. This will provide a check box that allows the user to login without entering the username and password.

Wednesday, October 25, 2006

How to setup RESTful Authentication

The following steps are tested on Mac OS 10.4.8

1. Create the Rails application: rails testr

2. Cd to testr directory. You need Rails 1.2 for this plugin, so:
rake rails:freeze:edge

3. Install the plugin: ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
(the command must be in one line)

4. Add the resouces in the config/routes.rb file (just below the first line):

map.resources :users, :sessions
map.signup '/signup', :controller => 'users', :action => 'new'
map.login '/login', :controller => 'sessions', :action => 'new'
map.logout '/logout', :controller => 'sessions', :action => 'destroy'

I also commented out the last line (default Rails 1.1 style routing).

5. Generate the migrations: ./script/generate authenticated user sessions

6. Generate mailer: ./script/generate authenticated_mailer user

7. Run mysql server

8. Specify the database password in database.yml file in config directory

9. Create testr_development database (Use CocoaSQL, YourSQL, MySQL Query Browser or command line)

10. Cd to db/migrate directory and run: rake db:migrate

11. Start the webserver: $testr > ./script/server

12. Point the browser to http://localhost:3000/signup

13. View the output of the signup process in the server console, you will see SQL insert statement.

14. Check the user table to see the newly created record.

15. Go to http://localhost:3000/login and http://localhost:3000/logout and play with the application.

I am getting sqlsock error in RailsLive CD environment. It has MySQL server 5.0. My mac has MySQL server 4.0 and it does not have any problems.

Monday, October 23, 2006

Getting Real - 37 SIgnals book

Last night I bought the "Getting Real" book from 37 signals and I finished
reading it. Here is the process that they have used with success:

1. Draw html mock-ups using paper and pencil. Easy to change and the cost of
throwing it away is negligible.
2. Create static html mockup for your site. Get feedback and make any
changes.
3. Code the most essential feature. Less is more. (They talk about
"Epicenter Design")
4. Release. Say no to all the features requested by customer. Incorporate
only those that align with the "Vision" for your software and is requested
by most of the customers.

In general there is no artifacts such as documentation, specification or
diagrams created during the product development. They are a waste of time
since no one can agree on issues. It is easier to know what we are building
and refine it when we play with the real thing.

It has helped me to think clearly and I have gained so much from this book.
I now have a blueprint for building a successful online business. I highly
recommend this book.

Rails Goodies

Agile Web Development with Rails covers the Model, View and Controller part of the Rails framework very throughly.

It falls short in AJAX and WebServices. OReilly's $10 pdf book on RJS and Webservices really rocks.

Money Train is another pdf book which is basically based on the RailsConf 2006 presentation. It contains very practical tips on Rails development.

Also $100 subscription to the RailsConf 2006 online video is not worth it. The quality of some of the videos is poor. The website has problems streaming the content. It drops the connection several times. Very frustrating experience. Half of the recordings have no video. I got the password for the site after 4 days.

There are some good presentations, I liked the DSL presentations. Google Reader is great, I subscribed for all the Rails related blogs and sites. It saved me money, I decided not to buy the RSS reader for Mac OS.

Thursday, October 19, 2006

Linux RailsLiveCD and VMWare Player on Windows

Booting the RailsLiveCD from the CD was problematic. Changed the BIOS setting to boot from CD, still no luck. Fortunately it is even better with VMWare player. It is free. This method also allows you to run both windows and Linux at the same time.

1. Download and install the free VMware player.
2. Download and install the generic virtual machine.
3. Rename the RailsLiveCD iso file to livecd.iso. Move this file to the same directory as the generic virtual machine.
4. Open the vmx file in the VMware player and enjoy.

This blog is more descriptive.

Tuesday, July 18, 2006

Subversion svn server

Pragmmatic Version Control - using Subversion is a very easy to read book. It makes it easy to learn about Subversion. This book will prepare you to move on to the free book on Subversion available at redbean. Search Rails mailing list for the actual link.

The reason for this post is that this explains about how to use the svn server to connect to your repository. I am running Subversion on my Powerbook. The IP address changes due to my ISP. In order to give a host name to my Mac I followed the instructions on the site Give your Mac OS X computer a hostname with DynDNS

It was easy to sign up for the account. However the article does not provide the following tips:

The website design makes it very difficult to navigate. Find the link for Home Solutions on the left navigation and go to "Official Macintosh/OS X Update Client". Download this and install it. Follow the instructions on the article I have mentioned above.

The update client will automatically map the dynamic IP of the machine to the host name you have selected.

Now you can enjoy working on your machine when you are away from home!!!

Monday, July 17, 2006

Subversion, RadRails, Subclipse and Eclipse

Installed Eclipse 3.2, Subclipse, and Eclipse Plugin for RadRails. You must install the RDT before installing RadRails, So grab this first http://updatesite.rubypeople.org/release and then this http://radrails.sourceforge.net/update

Otherwise you will get error message that the dependent library is not found.

The new version of standalone RadRails 0.7 is just out. I think it will be available for download anytime.

I don't know how to get rid of the missing JavaHL library in standalone RadRails. This prevented me from configuring the Subversion. This problem is happening in the other configuration also.

Got some help from Rails mailing list. Select the JavaSVN (Pure Java) as the SVN interface. The error message disappeared.

Thursday, June 01, 2006

Upgrading old rails application for new rails version

Run the following command from your application directory:

rake rails:update

This will update all the configs, scripts and javascripts to the latest
version.