Testing an application that implements the mobility gem with Minitest, a custom validator
class CustomValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if translation_exists?(record, attribute)
record.errors.add(attribute, options[:message] || :taken)
end
end
private
def translation_exists?(record, attribute)
attribute, locale = attribute.to_s.split('_')
record.class.joins(:string_translations).exists?(
mobility_string_translations: { locale: locale, key: attribute }
)
end
end
is invoked in the model as follows:
validates :name, presence: true
I18n.available_locales.each do |locale|
validates :"name_#{locale}", presence: true, custom: true
end
the model has a focus locale (that which is being learned) and is destined to populate the name
column and be present.
An array of translations also needs to be present (for now all available_locales).
But the following test fails:
test "validity of fixtures" do
assert tags(:en_assigned).valid?
end
because the fixture
en_assigned:
name: MyString
is deemed invalid as a puts tags(:en_assigned).errors.first.full_message
is adamant that
Name can't be blank
which is unexpected?
How can this setup be effectively tested?
This answer may be incomplete, but does address the issue.
The error arises in the database migration relative to the goal at hand.
class CreateTags < ActiveRecord::Migration[7.0]
def change
create_table :tags do |t|
t.string :element, index: true, null: false
[...]
the , null: false
is what gums up the works; the presence of mobility will populate the translation table, but not the class column. If one really desires to hold the original value and ensure it is not empty, it should be a separate column - unlss proven otherwise, at present, the saving of a master value in the column is not a funciotn carried out by the mobility
gem.
Then it becomes possible to define which locale(s) need to be validated by adjusting the above to something like:
[:de, :es].each do |locale|
validates :"name_#{locale}", presence: true, custom: true
end