views:

133

answers:

3

Hi All,

I have a table with a column called lifecycle_id, and another called lifecycle_change_reason. lifeycle_id is normally changed automatically by the system based on other factors, but certain users have the ability to change the lifecycle manually. if they do, I would like to require them to provide a reason for the change, but I don't want to require that field any other time. does anyone have a suggestion for how I can perform this type of validation?

thx :)

-C

A: 

I can see a couple different ways. I think the best would be to add another field to the table called something like lifecycle_id_original. Then your model would include code like this:

class Member < ActiveRecord::Base
  belongs_to :lifecycle

  validates :lifecycle_change_reason, :if => :lifecycle_changed?

  before_save :reset_original_lifecycle

  protected

  def lifecycle_changed?
    self.life_cycle_id != self.lifecycle_id_original && !self.lifecycle_id_original.nil?
  end

  def reset_original_lifecycle
    self.lifecycle_id_original = self.lifecycle_id
  end
end

When the object (member in this example) is validated, lifecycle_change_reason will only be required when the original and lifecycle_id are not identical. A nil value is also allowed for the original, because that's what it'll be when a record is newly created.

Then when it is saved, the "original" is set to match the lifecycle_id, so the next update cycle will work properly.

This isn't as clean as I'd like. My first thought was to use an attr_accessor so the duplicate isn't being stored in the DB all the time, but that would have meant setting that value every time a record is loaded. I'm not aware of any on_load style callbacks for ActiveRecord models.

Jaime Bellmyer
A: 

I do it like this

Tony
I don't really like it that much, but it works.thx-C
Chris Drappier
I don't love it but it's the most elegant way I have now
Tony
A: 

This seems like what the controller is for. I realize that people want to push logic to models, and for good reason, but let's be pragmatic here: if your system is changing this value automatically, and there is only a single point in your system where someone can change it manually, it does not, in my opinion, introduce all that much complexity to simply enforce the existence of a reason in your controller with something simple like:

if params[:object_name][:life_cycle_id] != @object.life_cycle_id && params[:object_name][:life_cycle_change_reason].blank?
   flash[:error] = "You must enter a reason for changing the life cycle."
   redirect_to :back and return false # or whatever
end
adriandz
the problem with this is you don't get all the nice validation error handling in the form.
Chris Drappier
Surely you know how to do that too though: @object.errors.add(:life_cycle_change_reason, "must be provided.")Simple.
adriandz