1
\$\begingroup\$

I have a form for an item (Job Item), that has sets of 2 fields based on a type.

field and field + _dolar

e.g: cogs_paid and cogs_paid_dollar

validation example: cogs_paid or cogs_paid_dollar, if both are empty, validation fails. This goes for all sub-fields.

What I did, my current Model:

 class JobItem < ActiveRecord::Base
 COGS_REQUIRED_TYPES = [
 ContentType::Brief,
 ContentType::Feature,
 ContentType::Fish,
 ContentType::Paid,
 ContentType::Print,
 ContentType::Target
 ].freeze
 include MessageBroker
 message_broker model_name: 'JobItem'
 belongs_to :job
 validates :weekly_budget, presence: { if: -> { COGS_REQUIRED_TYPES.include?(content_type) } }
 validates :cogs_brief_write_lead,
 presence: {
 if: -> { content_type == ContentType::Brief && cogs_brief_write_lead_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_brief_write_copy,
 presence: {
 if: -> { content_type == ContentType::Brief && cogs_brief_write_copy_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_brief_copy_edit,
 presence: {
 if: -> { content_type == ContentType::Brief && cogs_brief_copy_edit_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_write_lead,
 presence: {
 if: -> { content_type == ContentType::Feature && cogs_write_lead_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_interview,
 presence: {
 if: -> { content_type == ContentType::Feature && cogs_interview_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_write_feature,
 presence: {
 if: -> { content_type == ContentType::Feature && cogs_write_feature_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_content_edit,
 presence: {
 if: -> { content_type == ContentType::Feature && cogs_content_edit_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_copy_edit,
 presence: {
 if: -> { content_type == ContentType::Feature && cogs_copy_edit_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_paid_write_lead,
 presence: {
 if: -> { content_type == ContentType::Paid && cogs_paid_write_lead_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_paid_interview_research,
 presence: {
 if: -> { content_type == ContentType::Paid && cogs_paid_interview_research_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_paid_write_copy,
 presence: {
 if: -> { content_type == ContentType::Paid && cogs_paid_write_copy_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_paid_copy_edit,
 presence: {
 if: -> { content_type == ContentType::Paid && cogs_paid_copy_edit_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_paid_review,
 presence: {
 if: -> { content_type == ContentType::Paid && cogs_paid_review_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_paid_publish,
 presence: {
 if: -> { content_type == ContentType::Paid && cogs_paid_publish_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_design,
 presence: {
 if: -> { content_type == ContentType::Print && cogs_design_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_page_edit,
 presence: {
 if: -> { content_type == ContentType::Print && cogs_page_edit_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_page_proof,
 presence: {
 if: -> { content_type == ContentType::Print && cogs_page_proof_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 validates :cogs_photo_toning,
 presence: {
 if: -> { content_type == ContentType::Print && cogs_photo_toning_dollar.blank? },
 message: 'cant be empty or provide COGS Actual Cost matching entry',
 }
 def content_type=(value)
 new_type = ContentType.find(value)
 self[:content_type] = new_type ? new_type.id.to_s : nil
 end
 ContentType.types.each do |method, klass|
 define_method :"#{method}?" do
 content_type == klass
 end
 end
end

I currently have 20+ validations like the one above on my model, (for each sub-field and its type) which looks pretty ugly.

Any suggestions on how one would improve this, and reduce repetition?

What changes on every validation is:

field ; field+_dollar

content_type being compared: e.g ContentType::Paid

asked Oct 16, 2019 at 15:56
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

Changed to, on the model


 COGS_FIELDS_PRESENCE = [
 [content_type: 'brief', cogs_field: 'cogs_brief_write_lead', cogs_field_dollar: 'cogs_brief_write_lead_dollar'],
 [content_type: 'brief', cogs_field: 'cogs_brief_write_copy', cogs_field_dollar: 'cogs_brief_write_copy_dollar'],
 .
 .
 . + 20 entries
 ]
 def cogs_fields_presence
 COGS_FIELDS_PRESENCE.flatten.each do |field|
 if content_type.to_s == field[:content_type] && self[field[:cogs_field]].blank? && self[field[:cogs_field_dollar]].blank?
 errors.add(field[:cogs_field], 'cant be empty or provide COGS Actual Cost matching entry')
 end
 end
 end
answered Oct 23, 2019 at 21:14
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.