bookmark_borderrails captcha and testing using mock objects

To prevent bots from Signing up on our application, we added a captcha to our User model. We used the validates_captcha plugin available at http://svn.2750flesk.com/validates_captcha/trunk

The plugin, selects text from a String array for the captcha challenges, so, Sur, my co-programmer, hacked the plugin a little to add random text and improved images.

After adding the plugin we realized that all our tests which validate the User model had started failing. Programmatcially a test case or a bot are not much different, they are both scripts.

Mocks to the rescue.

Here is what I wrote in a file named add_captcha_to_active_record.rb under test/mocks/test directory.


require File.expand_path(File.dirname(__FILE__) + 
"/../../../vendor/plugins/validate_captcha/lib/add_captcha_to_active_record")

module AngryMidgetPluginsInc #:nodoc:

	module Validations #:nodoc:

		# module Captcha
		module Captcha #:nodoc:

			# module InstanceMethods
			module InstanceMethods #:nodoc:

			private

				def validate_captcha(options = {}) #:nodoc:
				  
				end

			end

		end#module Captcha

	end#module Validations

end#module AngryMidgetPluginsInc

What I have done by adding this file is, I have asked the test scripts to use the validates_captcha method in /test/mocks/test/add_captcha_to_active_record.rb instead of the validates_captcha method in plugins/validate_captcha/lib/add_captcha_to_active_record.rb

Well actually Rails does all the magic, I just need to give the same file name as the one I want to mock and then define the method that I want to override.

The original validates_captcha method checks that the text entered on the signup screen is the same as that stored on the server. If these do not match it adds a validation error to the base class, the User class in our case.
In the mock validates_captcha method we just do nothing. So a validation error will never be added to the base class.

And now our tests are running and passing again.

I also noted the presence of a directory /test/mocks/development/ … well that means I can even mock classes in the development environment.
One of our application, connects to Paypal to make a payment and then returns back. During development we had commented out this code so that we are not sent to paypal everytime. Now I know how I can avoid commenting or changing the code by using mock objects.
I will be working on that soon and blog about my experiences here.

bookmark_bordervalidating Rails association

Should ActiveRecord add validations based on associations defined in the models?


class User < ActiveRecord::Base 
  has_many :posts 
end 

class Post < ActiveRecord::Base 
  belongs_to :user 
end 

If i create an instance of a post with a user_id that does not exist in the Users table, I wish ActiveRecord threw up a validation error on saving this instance of post.
It does not do so by default, so here are the validations that I add to my models to implement this.


class User < ActiveRecord::Base 
  has_many :posts 
end 


class Post < ActiveRecord::Base 
  belongs_to :user 
  validates_associated :user 
  validates_presence_of :user 
end 


Now if I try and save a post without a user_id or with a user_id that is not found in the Users table, an exception is thrown.

Till now I always use to create foreign keys in my database, as a safety net. So that the db throws an error if my data is not consistent.
After adding these validations, I hope not to have foreign keys in the database anymore.

bookmark_borderPolymorphic Association in Rails

Here is an account of my first use of Rails 1.1’s polymorphism in Model associations.

I had looked at all the examples at the wiki and a couple of other blogs but still wasn’t clear.

You appreciate most, the problems that you solve yourselves 🙂

Here is the problem I solved using Polymorphic associations.

Consider the scenario where there are Users of an application; who can act as both buyers and providers. Each user can infact have multiple buyer and provider profiles.
The application also has a messaging system for users to contact each other.
As a part of the application requirement, we need to keep track of the profiles of the message sender and receiver.

A user logs in using the login name and password present in the User model. I am omitting details so please assume for this example that each logged in user, has either a buyer profile or a provider profile associated to it, when they use the messaging system.

Here are the model files

A user can have many buyer_profiles and many provider_profiles


class User < ActiveRecord::Base
  has_many :buyer_profiles
  has_many :provider_profiles
end

A buyer profile belongs to a user and can have many messages associated to it as a sender and as a receiver.


class BuyerProfile < ActiveRecord::Base
  belongs_to :user
  has_many :messages, :as => :sender
  has_many :messages, :as => :receiver
end

A provider profile also belongs to a user, and can have many messages associated to it as a sender and as a receiver.


class ProviderProfile < ActiveRecord::Base
  belongs_to :user
  has_many :messages, :as => :sender
  has_many :messages, :as => :receiver 
end

The message model holds the polymorphic magic, via the two interfaces sender and receiver. A message belongs to sender which can be polymorphic,either a buyer or a provider. And also a message belongs to a receiver, which again is polymorphic, either a provider or a buyer.


class Message < ActiveRecord::Base
  belongs_to :sender, :polymorphic => true
  belongs_to :receiver, :polymorphic => true
end

The code above requires that I have these four special fields in my messages table to handle polymorphism. Here is the migration for messages


class CreateMessagesTable < ActiveRecord::Migration
  def self.up
    create_table :messages do |t|
      t.column :sender_id, :integer
      t.column :sender_type, :string
      t.column :receiver_id, :integer
      t.column :receiver_type, :string
      t.column :subject, :string
      t.column :message, :string
    end
  end

  def self.down
    drop_table :messages
  end
end

I ran the following code on the console to check if everything is working as expected.


r = BuyerProfile.find(1)
s = ProviderProfile.find(1)
m = Message.new
m.sender = s
m.receiver = r
m.subject = "test subject"
m.message = "test message"
m.save!

And it worked 🙂

I could access profles and users from the message object like this.


m = Message.find(1)
m.receiver                 # refer to the receivers profile object
m.receiver.class          # get receiver type, where BuyerProfile or SellerProfile
m.sender                   # refers to the sender profile object
m.sender.class            # get sender type, where BuyerProfile or SellerProfile
m.receiver.user           # refer the User object of the message receiver
m.sender.user             # refer the User object of the message sender

Polymorphism saved me a lot of time and also a whole new table which I was thinking of adding to handle this functionality prior to polymorphism.

Added : And yes, now I am thinking about what I would need to write to get all the messages sent or received by a User.

bookmark_borderRailsConf Europe 2006…. here i come.

Signed up for RailsConf Europe 2006, London September 14-15. It’s EXPENSIVE as compared to Chicago RailsConf in June. But I think the airfare will even out things for me. And the chicago conference got booked so fast, that I didn’t even get a chance to think seriously about attending it.

The conference is already packed with exciting speakers, including the creator of Rails, David Heinemeier Hansson, Pragmatic Programmer Dave Thomas, best-selling author and passion maven Kathy Sierra, Rails core developers Jamis Buck, Marcel Molina, Jr., Thomas Fuchs, Rails authors and trainers David Alan Black, and Chad Fowler, Rake author Jim Weirich and many more to be announced.

Sound like it’ll be fun …if you would be there too …. ping me and let’s meetup.

bookmark_borderDRY in Views

Don’t Repeat yourself while creating Views in Rails.

I was confused when I starting working on Rails … but now I apply these rules.

Use Layouts to create page layouts to be shared by all views rendered by a controller.

Use components to create controller actions whose output needs to be used more than once

Use partials to create views, which need to be rendered more than once, in the same action or in different actions. [see collection option to render partial more than once in the same action]

bookmark_borderruby code block and iterators

Code Blocks and Iterators are a very useful feature in Ruby.

An iterator is a method that executes a block of code.

Say we have a method named each


def each(array)
    #do something
end

The block is specified next to the method call, after the last parameter to the method.


names=['alice', 'bob', 'charlie', 'dave']
each(names) { |s|  puts s }

Our block is the code within the { } braces. (mutiple line block can be written between do….end)

We are passing an array names, in the call each(names).
Inside each() we will iterate through this array names.


def each(arr) 
  for i in 0..arr.size-1 
    yield arr[i] 
  end 
end 

All the code block iterator’s magic is done by the yield statement.

The yield statement invokes the code in the block.
The yield statement can also pass parameters to the block . In our example, the array element at position i is passed to the block. The block receives this parameter between vertical bars or pipes. (|s| in our example)

A block may also return value to the yield. The last expression evaluated in the block is passed back as the value of the yield.

Here is the complete listing of our code so far


def each(arr) 
  for i in 0..arr.size-1 
    yield arr[i] 
  end 
end 
names=['alice', 'bob', 'charlie', 'dave']
each(names) { |s| puts s } 

This code will print all the array elements, as yield is called for each array element. Yield in turn invokes the code block passing it the array elements, the code block puts the element.

We could change the block code to print all the array element in upper case or in reverse.


each(names) { |s| puts s.upcase } 
each(names) { |s| puts s.reverse } 

What we have done so far, is actually provided builtin by ruby for various types of collections.

each is a builtin iterator in ruby which yield the elements of the collection.
To print all elements of array names we could simply do


names.each { |name|  puts name }

Similarly there is a find iterator.
To print all names that begin with m, we could use


m_names = names.find { |name| name.index('m') == 0 } 
m_names.each { |name| puts name } 

Iterators help a lot in keeping ruby on rails code compact. I have been using them a lot, ever since i discovered them.

bookmark_borderRails:join table name

I just came across the naming convention for a has_and_belongs_to_many relation’s join table.

If you have tables products and categories, which have a many to many relationship, a product can belong to many categories and a category can contain many products. What would you name the joining table, products_categories or categories_products.

Rails convention says use categories_products.

Rails assumes that a join table is named after the two tables it joins (with the names in alphabetical order). If you use some other name, you would need an additional declaration.

Unless there is a very compelling reason to do so, one should stick with the convention.
Reason: For maximum productivity don’t go against Rails’ philosophy “Convention over configuration”