Skip to content

Instantly share code, notes, and snippets.

@tomasc
Last active August 17, 2018 09:22
Show Gist options
  • Save tomasc/9951ed039bd7f59ac1f63dd54b4290e4 to your computer and use it in GitHub Desktop.
Save tomasc/9951ed039bd7f59ac1f63dd54b4290e4 to your computer and use it in GitHub Desktop.
localized_presence_validator
# adds following new options to presence validator:
#
# • presence: :cs
# • presence: %i[cs en]
# • presence: :default_locale
module LocalizedPresenceValidator
def validate_each(document, attribute, value)
field = document.fields[document.database_field_name(attribute)]
return super(document, attribute, value) unless field.try(:localized?)
in_option = options.fetch(:in, nil)
with_option = options.fetch(:with, nil)
with_option = ::I18n.default_locale if with_option == :default_locale
locales = Array(in_option || with_option).select { |l| ::I18n.available_locales.include?(l.to_sym) }
if locales.present?
locales.each do |_locale|
_value = value.fetch(_locale.to_s, nil)
next unless not_present?(_value)
document.errors.add(
attribute,
:blank_in_locale,
options.merge(location: _locale)
)
end
else
super(document, attribute, value)
end
end
end
Mongoid::Validatable::PresenceValidator.send(:prepend, LocalizedPresenceValidator)
class LocalizedPresenceValidatorDoc
include Mongoid::Document
field :field_1, type: String
field :localized_field_1, type: String, localize: true
field :localized_field_2, type: String, localize: true
field :localized_field_3, type: String, localize: true
field :field_4, type: String
validates :field_1, presence: true, on: :default
validates :localized_field_1, presence: true, on: :default_localized
validates :localized_field_2, presence: %i[cs], on: :locales_only
validates :localized_field_3, presence: :default_locale, on: :default_locale_only
validates :field_4, presence: :default_locale, on: :default_locale_only_on_non_localized
end
require 'test_helper'
describe LocalizedPresenceValidator do
let(:klass) { LocalizedPresenceValidatorDoc }
describe 'default' do
let(:context) { :default }
it { klass.new(field_1: 'TEST').valid?(context).must_equal true }
it { klass.new(field_1: nil).valid?(context).must_equal false }
end
describe 'default localized' do
let(:context) { :default_localized }
it { klass.new(localized_field_1: 'TEST').valid?(context).must_equal true }
it { klass.new(localized_field_1: nil).valid?(context).must_equal false }
end
describe 'specified locales only' do
let(:context) { :locales_only }
before do
@available_locales = ::I18n.available_locales
::I18n.available_locales = %i[en cs]
end
after do
::I18n.available_locales = @available_locales
end
it { klass.new(localized_field_2_translations: { 'cs' => 'TEST', 'en' => nil }).valid?(context).must_equal true }
it { klass.new(localized_field_2_translations: { 'cs' => nil, 'en' => 'TEST' }).valid?(context).must_equal false }
end
describe 'default locale only' do
let(:context) { :default_locale_only }
before do
@available_locales = ::I18n.available_locales
::I18n.available_locales = %i[en cs]
end
after do
::I18n.available_locales = @available_locales
end
it { klass.new(localized_field_3_translations: { 'en' => 'TEST', 'cs' => nil }).valid?(context).must_equal true }
it { klass.new(localized_field_3_translations: { 'en' => nil, 'cs' => 'TEST' }).valid?(context).must_equal false }
end
describe 'default locale only on non localized' do
let(:context) { :default_locale_only_on_non_localized }
it { klass.new(field_4: 'TEST').valid?(context).must_equal true }
it { klass.new(field_4: nil).valid?(context).must_equal false }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment