Pregunta

I have model patient. When patient try to register, he fills fields, for example: name, email, telephone, and there is validation presence on this fields. Also i have another form in which doctor can add patient for himself, this form has only one field name.

Question: can I somehow skip validation on fields email and telephone but leave validation on name?

At the moment, i have this action:

def add_doctor_patient
  @patient = @doctor.patients.new(patient_params)
  if params[:patient][:name].present? and @patient.save(validate: false)
    redirect_to doctor_patients_path(@doctor), notice: 'Added new patient.'
  else
    render action: 'new'
  end
end

When name is present in params I skip validation and save patient, but when name doesn't present, it will just render new action with out error, and simple_form will not mark field in red color. Maybe there is way to raise error, or just another solution?

UPD

Solution: following the wintermeyer answer. As I have relation patient belongs_to: doctor, I can use - hidden_field_tag :doctor_id, value: @doctor.id, and make check like guys said, unless: ->(patient){patient.doctor_id.present?}. P.S if someone use devise we should also skip devise required validation on email and password. We can add to model, in my case Patient, something like this:

def password_required?
  false if self.doctor_id.present?
end

def email_required?
  false if self.doctor_id.present?
end
¿Fue útil?

Solución 2

It seems to be such a simple question but the longer I think about it the more possible solutions come up. I have a hard time to tell which one is the DRYest. The quick and dirty solution would be to add a hidden boolean field xyz in the doctor's form. You'd have to add that attribute on the bottom of your controller if you are using Rails 4. With that you could do something like this in your model:

validates :name,  presence: true
validates :email, presence: true, unless: ->(patient){patient.xyz.present?}

Otros consejos

What I like to do is (in the model):

attr_accessor :skip_validations

validates :name, presence: :true
validates :email, presence: :true, unless: :skip_validations
validates :telephone, presence: :true, unless: :skip_validations

then in the controller:

patient = Patient.new(patient_params)
patient.skip_validations = true

Altough it does the same as the other answers I find it cleaner.

You can do something like that:

 validates :name,  presence: true
 validates :email,  presence: true, unless: ->(patient){patient.name.present?}

I would add an extra field to patient, which would indicate if a patient is self-registered or not.

So for instance add a field source which could either be patient or doctor, or a boolean field self_registered which is true if a patient registered herself.

Your validation would then become

validates :name, presence: true
validates :email, presence: true, if: -> (patient.is_self_registered?)

Using a temporary field only works when creating the user, but when editing/updating the user in a later stage will fail (since at that time you will no longer know if the patient did or did not register herself ----you could assume it, but never know for sure).

I wrote a gem that accomplishes this sort of "conditional" validation. My conclusion is that the best way to accomplish conditional validation is to have the controller decide when to enable any non-standard validation rules. So, if you're following RESTful practices as much as you can then you should have a different controller for the doctor vs the patient form submission. Or if not then at least some way to tell, right? In any case, the controller can then direct the models on what to do validation-wise. Here's a link to the gem... hopefully it feels right for your situation too:

https://github.com/pdobb/conditional_validation

Basically, it provides a few wrapper methods around a virtual attribute that you setup that I call the "validation_accessor". It then provides syntactic sugar for the same sort of thing the others are suggesting in this thread.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top