Trying to make things nicer

I have a Project model, which has a status property. Status can either
be 0, 1, 2, or 3 - and complies with the array Project.statuses = [
:hidden, :available, :in_progress, :complete ]. This works well in all
of my application, tested and all. (Project.statuses is only used
superficially at this point, and I added Project#complete?,
Project#in_progress?, etc. - automatically - this works too)

Now, in my unit tests, I often had to set the status of the project
manually. Now, I could do this in many different ways, but I’ve set my
eyes on this one:

some_project.status = :complete

To get this to work, what I did was (in project.rb)

def status=(new_status)
if (new_status.is_a? Symbol) || (new_status.is_a? String)
new_status = Project.status_id_for new_status
end

super new_status

end

Project.status_id_for being a proper lookup (with some aliases, for
example :assigned is same as :in_progress). This works perfectly within
the testing code, and from the console.

However, this code breaks updating using the controller - the
mostly-scaffold code calls @project.update_attributes(params[:project])
(params[:project][‘status’] is set by the form to the proper numeric
value), but that, for some reason, sets @project.status to nil (which is
invalid, and I test for with validates_presence_of :status).

Now, removing my special status= method brings things back to normal,
and I could obviously do without this, but… I mean, come on, that’s
just beautiful. Any chance of this working without an ugly hack?

I don’t know of an easy way to do this…anyone?

Starr

www.thebootstrapnation.com

Actually, now that I think about it, you could use model callbacks to
do the translation for you before saving and after loading.

Starr

www.thebootstrapnation.com

DOH!!!

Remember kids, numeric values from forms - even selections - get passed
into the controller as strings. So new_status was ‘2’, not 2, and
status_id_for(‘2’) == nil.

This code works:

def status=(new_status) #:nodoc:
if (new_status.is_a? Symbol) || (new_status.is_a? String)
# If we don’t have that status in Project.statuses, leave
# new_status alone.
new_status = Project.status_id_for(new_status) || new_status
end

super new_status

end