Reputation: 3398
I wanna do a validation that sums the values of nested fields so I make sure it's 100%. So, in my parent model, I would do the validation, and do a self.errors.add
and add the error if the validation fails. The problem is, the errors.add
as long as I know expects some attribute as argument, but it's not related to any attribute on my parent model, so I would like to display that message on the top of the form, for example. Any ideas of how I can do that? thank you!
UPDATE:
This is my parent model, where I wanna validate. The form has nested fields for :arrendamento_contrato_unidades.
class ArrendamentoContrato < ApplicationRecord
has_many :arrendamento_contrato_unidades, dependent: :destroy
validate :check_total_percentual_credito
def check_total_percentual_credito
if arrendamento_contrato_unidades.sum(&:percentual_credito).to_f != 100.0
self.errors.add :base, "Tem que ser 100%"
end
end
end
My create method, which it's the one I'm testing:
def create
@arrendamento_contrato = ArrendamentoContrato.new(arrendamento_contrato_params)
respond_to do |format|
if @arrendamento_contrato.save
format.html {
flash[:notice] = flash_notice
redirect_to action: "index"
}
format.json { render json: {status: 1, redirect: arrendamento_contratos_url} }
else
format.html { render :new }
format.json { render json: {status: 0, errors: @arrendamento_contrato.errors, status: :unprocessable_entity} }
end
end
end
--- Also, I debugged my object.errors.full_messages on the form, and the error is there. It's only not being displayed!
I guess that add errors to the base it's what I'm looking for. But now, it's not showing my message, but only that I have validation errors. My form code:
= simple_form_for(@arrendamento_contrato, validate: true, html: { id:"dropzoneForm", class: "dropzone dz-clickable"}) do |f|
= f.error_notification
.form-inputs
.row
.col-md-6
= f.input :numero
.col-md-6
= f.association :usina, input_html: {class: "chosen-select"}
.hr-line-dashed
.row
.col-md-6
= f.association :esco_contrato, input_html: {class: "chosen-select"}
.col-md-6
= f.association :om_contrato, input_html: {class: "chosen-select"}
.hr-line-dashed
.row
.col-md-4
= f.input :data_inicio, as: :string, input_html: {"data-mask" => "date"}
.col-md-4
= f.input :data_fim, as: :string, input_html: {"data-mask" => "date"}
.col-md-4
= f.input :valor_mensal, as: :string, input_html: {"data-mask" => "decimal"}
.hr-line-dashed
#arrendamento_contratos_unidades
- if !@arrendamento_contrato.arrendamento_contrato_unidades || @arrendamento_contrato.arrendamento_contrato_unidades.empty?
h3 = I18n.t('activerecord.models.unidade_consumidora.other')
i
'Aguardando ESCO...
- else
.row
.col-md-6
label class='control-label'
= I18n.t('activerecord.models.unidade_consumidora.other')
.col-md-6
label class='control-label'
= I18n.t('activerecord.attributes.arrendamento_contrato_unidade.percentual_credito')
.hr-line-dashed
.blockquote
= f.simple_fields_for :arrendamento_contrato_unidades do |f|
= render 'arrendamento_contrato_unidade_fields', f: f
.hr-line-dashed
Upvotes: 1
Views: 2832
Reputation: 51
i guess it should work for you
https://apidock.com/rails/ActiveRecord/Errors/add_to_base
just
errors.add_to_base("")
Upvotes: 2
Reputation: 337
Updating the answer for this common question and if anybody finds it useful. You can use Errors#add(:base, msg)
instead
I.E.
def validate_method
errors.add(:base, 'Error message') if some_logic
...
end
Upvotes: 0
Reputation: 1885
I think Jeff was on the right path, but I think the method you are supposed to use is model_instance.errors[:base]
.
I think you also might want to take into account the over all design of this feature (not that I have the full context of your app). if you have a validation of the parent model on its children model's it means that you will be saving erroneous children model to your data base only to then notify the user. Since it seems like this would be done with nested attribute you may want to consider doing this in the controller but there is an argument to be made about having too much logic in your controller.
Upvotes: 1