public
Last active

Ruby Translatable

  • Download Gist
translatable.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
# Motivation:
# Wanted a more solid way to test validation resulted in correct errors
# other than matching strings;
# Decoupling the very notion of error from message
#
# Sideeffects:
# - Conventional way to namespace error translation by actual path
 
 
module Translatable
 
# this is what all this is about
def to_s
I18n.t i18n_key, {default: default_translation}.merge(i18n_options)
end
 
# Usage
# SomeTranslatable.new(...).interpolating(bleh: 'huh')
def interpolating additional_options
tap{i18n_options.merge! additional_options}
end
 
 
def self.interpolating *args
translatable, additional_options = args
case translatable
when self then translatable.interpolating(additional_options)
else translatable
end
end
 
def i18n_options
@i18n_options ||= {}
end
 
 
def to_s
I18n.t i18n_key, {default: default_translation}.merge(i18n_options)
end
 
 
def i18n_key
self.class.name.underscore.gsub(?/,?.)
end
 
def default_translation
self.class.name.underscore.split(?/).last.gsub(?_,' ')
end
 
def empty?; false end # for AM::Validations
 
end
translatable_spec.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
require_relative '../../lib/translatable'
require 'i18n'
require 'active_support/core_ext/string'
 
describe Translatable do
 
 
class YourModel
module Errors
class SomethingIsWrong
include Translatable
end
end
end
 
subject{YourModel::Errors::SomethingIsWrong.new}
 
before{I18n.reload!}
 
its(:to_s){should eq 'something is wrong'}
 
describe '#interpolating' do
it 'Stores interpolation bits for later use with matching i18n translation' do
I18n.backend.store_translations I18n.locale,
your_model: {errors: {something_is_wrong: 'Very bad %{stuff} happened'}}
 
expect("#{subject.interpolating(stuff: 'crap')}").to eq \
'Very bad crap happened'
end
end
 
 
describe '.interpolating' do
it 'ignores non-translatables' do
regular_error_message = 'Oh damn!'
expect(Translatable.interpolating(regular_error_message,
this_goes_nowhere: 'Uh-oh')).to eq \
'Oh damn!'
end
 
it 'adds interpolation bits to translatable' do
I18n.backend.store_translations I18n.locale,
your_model: {errors: {something_is_wrong:
'Very bad %{stuff} happened. Probably connected to %{cause}'}}
 
original_error = subject.interpolating(stuff: 'crap')
 
error_with_additional_details_added_higher_in_call_stack =
Translatable.interpolating(original_error, cause: 'aliens')
 
expect("#{error_with_additional_details_added_higher_in_call_stack}").to eq \
'Very bad crap happened. Probably connected to aliens'
end
end
 
 
example do
kinda_activemodel_errors = {}
kinda_activemodel_errors['Some attribute'] =
[YourModel::Errors::SomethingIsWrong.new, 'some regular error']
 
kinda_activemodel_errors['Some attribute'].should \
include(be_a(YourModel::Errors::SomethingIsWrong))
end
 
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.