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

\$\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
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.