The Accelerate HR Blog

Help! My Booleans Are Not Nil !   (Mon Nov 26 2007)

I come from a land where boolean is either true or false.

And in Ruby on Rails it's been hard to come to terms with the fact that boolean can be true or false OR nil. Hard, but extremely useful !

I was setting up the basic rules and parameters for a payroll. To get started, the user needs to answer a series of questions. Like 'Does personal taxation apply in this location?' (Yes, there are still countries where there's no tax! ) 'Does national insurance apply?' 'Do some employees earn a gratuity at the end of service?' 'Do you have a staff savings or pension scheme?' Their answers are going to be used to make the payroll set-up a breeze.

What I could have done is set a default on each of the boolean fields to true or false. But that's not what I wanted. I need to see evidence that users have actually considered and answered each of the questions; it's important that they should get this right before they move on. So the default is nil (or NULL if you want to MySql it). And then, in the model, I set up a method to find out whether all the questions have been answered before allowing them to move on.

It all seemed easy enough at first. I created a model payrollparameter and migrated in fields like this:

class CreatePayrollparameters < ActiveRecord::Migration
def self.up
create_table :payrollparameters do |t|
t.column :location_id, :integer
t.column :taxation, :boolean
t.column :insurance, :boolean
t.column :gratuity, :boolean
......
end
end
..............
end

And then I needed to set up the method in the location model. Something like this, I thought: -

def has_payroll_parameters
@p = Payrollparameter.find(:first, :conditions => [ "location_id = ?", self.id])
if @p.taxation.nil? and @p.insurance.nil? and @p.gratuity.nil?
return false
else
return true
end
end

And finally in the payrollparameter controller:

def update
@payrollparameter = Payrollparameter.find(params[ :id])
if @payrollparameter.update_attributes(params[ :payrollparameter])
if @payrollparameter.location.has_payroll_parameters == false
flash[ :warning] = "You must answer all the questions before you continue."
redirect_to :action => 'index'
else
flash[ :notice] = 'Your payroll rules were successfully updated."
redirect_to :controller => ..................
end
else
.................
end
end

Nice idea ... but it doesn't work. It's fine while you haven't answered all the questions. Click on 'Save changes' and the update action correctly refreshes the index page with the warning that you haven't answered all the questions.

But it all breaks down when you've answered all the questions, when everything is either true or false. Then there's a nasty error message telling you that Ruby's not coping with the nil values on the boolean fields.

So what to do? Well, I could have decided not to use a boolean, I guess. Set the fields to an integer, with 0 as unanswered, 1 as false and 2 as true. But somehow that just didn't feel right.

So instead I changed the method name to has_payroll_parameters? The question-mark shows Ruby that the method is expected to return either true or false, so we can get rid of the if ... return false ... else ... return true.

Next, to test whether or not the fields have a value, it's sufficient to say:

@p.taxation and @p.insurance and @p.gratuity

So the revised method in the model is:

def has_payroll_parameters?
@payrollparameter = Payrollparameter.find(params[ :id])
@p.taxation and @p.insurance and @p.gratuity
end

Better. Shorter. Neater.

So on to the controller. And here I had a little trouble working things out at first. In the 3rd line of the update action, I tried:

if @payrollparameter.location.has_payroll_parameters?

Still not right. When I answered all the questions, the controller was still sending me back to the index page with the error message.

And this is where the ever-useful console came to the rescue. Firing up ruby script/console, I set the location:

>> @location = Location.find_by_id(3)

Then with all the questions answered:

>> @p = @location.has_payroll_parameters?
-> false

So then I tried again, but this time I restored some of the question-fields to their original NULL settings. The console returned a different result:

>> @p = @location.has_payroll_parameters?
-> nil

Aha. So the first time, when I'd answered all the questions, some with true and some with false as the response, the method returned a false because not all the statements were true. The second time it returned a nil because not all the questions had been answered. has_payroll_parameters? doesn't have a value yet.

And that immediately gave me what I needed and I was able to correct the controller:-

def update
@payrollparameter = Payrollparameter.find(params[ :id])
if @payrollparameter.update_attributes(params[ :payrollparameter])
@pp = @payrollparameter.location.has_payroll_parameters?
if @pp.nil?
flash[ :warning] = "You must answer all the questions before you continue."
redirect_to :action => 'index'
else
flash[ :notice] = 'Your payroll rules were successfully updated."
redirect_to :controller => ..................
end
else
.................
end
end

It's not rocket science, but it helped me. And hopefully if you're just starting out with Ruby and Rails, it'll help you. Want more posts like this with details of how I'm trying to deal with the problems I meet? Then just let me know. And if you've got a better way - then I'm all ears... well, eyes really.

Filed under: Ruby on Rails






List recent Entries
List all blog entries filed under:

Employment Politics
HR
Implementation
Just thoughts
Ruby on Rails
Web 2.0

Can't find what you're looking for? Try this: -

Search blog for a word or phrase



 Subscribe to an RSS feed

Or get an email copy every time we post something new. Nothing new? Nothing mailed

Enter your email address:

Delivered by FeedBurner


If you're enjoying our blog, why not find out more, and maybe get involved?

ACCELERATE HR is a website built on Rails and designed for the enterprise. And we're building it live on the Web, right here.

Check out our home page HERE, or sign up for free HERE.


DESERT ISLAND BLOGS

Sharing a few of my favorites

HR Stimuli
McArthur's Rant

Jon Ingham's Strategic Human Capital Management Blog

The Rails Track
Railscasts

Web Power
The Technology Edge

Window on the Gulf
Mahmood's Den