Skip to content

Instantly share code, notes, and snippets.

@cec
Created September 11, 2013 16:07
Show Gist options
  • Save cec/6525812 to your computer and use it in GitHub Desktop.
Save cec/6525812 to your computer and use it in GitHub Desktop.
Rails 3.2 - Custom validator class on parent model, clashing with validates_associated :child_models
# encoding: utf-8
class Event < ActiveRecord::Base
include LocalizedTexts
has_many :texts, :class_name => 'EventText', :dependent => :destroy, :inverse_of => :event
validates_with MultiTextValidator
validates_associated :texts
end
#encoding: utf-8
class EventText < ActiveRecord::Base
belongs_to :event, inverse_of: :texts
validates_presence_of :title, :intro
validate :pricing_details
private
def pricing_details
unless event.free? ^ pricing.present?
msg = pricing.present?() ? "error_message_1" : "error_message_2"
errors[:pricing] << msg
end
end
end
# encoding: UTF-8
# This validator checks common validation rules for all models having associated text models
class MultiTextValidator < ActiveModel::Validator
cattr_reader :error_messages
@@error_messages = {
italian_missing: 'activemodel.errors.event.texts.italian_missing',
non_unique_languages: 'activemodel.errors.event.texts.non_unique_languages',
}
def validate record
italian_required record
unique_languages record
end
private
def italian_required record
unless record.texts.find { |t| t.language == :it }
message = I18n.t self.class.error_messages[:italian_missing]
record.errors.add :base, message
record.errors.add :texts, message
record.texts.last.errors.add(:language, message) unless record.texts.empty?
end
end
def unique_languages record
languages = record.texts.map(&:language)
return if languages.uniq.length == languages.length
counts = {}
languages.uniq.each { |l| counts[l] = ( record.texts.to_a.count {|text| text.language == l} ) }
counts.delete_if { |k, v| v == 1 }
non_unique_languages = counts.keys
non_unique_languages.each do |lang|
message = I18n.t(self.class.error_messages[:non_unique_languages], language: lang)
record.errors.add :base, message
record.texts.each do |t|
t.errors.add(:language, message) if t.language == lang
end
end
end
# Association Reflection Fancyness
def supported_languages record
record.class.reflect_on_association(:texts).options[:class_name].constantize::LANGUAGES
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment