简体   繁体   中英

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 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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM