开发者

how do i validate the presence of a field only if another field was edited in rails?

I have a table with a column called lifecycle_id, and another called lifecycle_change_reason. lifeycle_id 开发者_如何学Cis 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


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.


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜