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