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!