Skip to content

Commit

Permalink
Merge pull request #6 from doits/lower_gc_pressure
Browse files Browse the repository at this point in the history
Lower gc pressure
  • Loading branch information
attilahorvath authored Sep 9, 2016
2 parents 5d10cbf + 838b993 commit 6ff3101
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 5 deletions.
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
language: ruby
rvm:
- 2.0
- 2.1
- 2.2.5
- 2.3.1
- ruby-head
matrix:
allow_failures:
- rvm: ruby-head
2 changes: 2 additions & 0 deletions i18n-globals.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']

spec.required_ruby_version = '>= 2.0'

spec.add_development_dependency 'bundler', '~> 1.6'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'minitest'
Expand Down
30 changes: 25 additions & 5 deletions lib/i18n/globals.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require 'i18n/globals/version'

module I18n
FAKE_INTERPOLATION_HASH = { fake_: :_interpolation }.freeze

class Config
class CachedGlobals < Hash
def []=(key, val)
Expand Down Expand Up @@ -79,15 +81,33 @@ def globals
def globals=(new_globals)
globals.clear.merge!(new_globals) # maybe there is something better than `clear` and `merge!`
end

prepend(
Module.new do
def missing_interpolation_argument_handler
@@missing_interpolation_argument_handler_with_globals ||=
lambda do |missing_key, provided_hash, string|
# Since the key was not found in a interpolation variable, check
# whether it is a global. If it is, return it, so interpolation is
# successfull.
if globals.for_locale(locale).key?(missing_key)
globals.for_locale(locale)[missing_key]
else
super.call(missing_key, provided_hash, string)
end
end
end
end
)
end

class << self
def translate(*args)
if args.last.is_a?(Hash)
args[-1] = config.globals.for_locale(locale).merge(args.last)
else
args << config.globals.for_locale(locale)
end
# If last argument is a hash, interpolation will be run. If not, it will
# not even attempt to interpolate something and our custom
# `missing_interpolation_argument_handler` will not be run at all. Thats
# why we pass in a fake hash so that it always runs interpolation.
args << FAKE_INTERPOLATION_HASH unless args.last.is_a?(Hash)
super(*args)
end

Expand Down
45 changes: 45 additions & 0 deletions test/test_i18n_globals.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,49 @@ def test_that_cache_is_cleared_after_merging_a_new_global

assert_equal 'Hi there, Dobby!', I18n.translate('greeting')
end

def test_it_still_fails_on_missing_interpolation
assert_raises(I18n::MissingInterpolationArgument) { I18n.translate('greeting') }
end

def test_it_allows_to_set_a_custom_missing_interpolation_argument_handler
I18n.config.missing_interpolation_argument_handler = proc { raise 'works!' }

assert_raises('works!') { I18n.translate('greeting') }

I18n.config.missing_interpolation_argument_handler = nil
end

def test_it_translates_globals_with_custom_missing_interpolation_argument_handler
I18n.config.missing_interpolation_argument_handler = proc { raise 'works!' }

I18n.config.globals = {
name: 'Greg'
}

assert_equal I18n.translate('greeting'), 'Hi there, Greg!'

I18n.config.missing_interpolation_argument_handler = nil
end

def test_it_does_not_polute_the_object_space_with_hashes
I18n.config.globals = {
name: 'Greg'
}

values = { name: 'Dobby' }
times = 10_000

GC.disable
count_before = ObjectSpace.each_object(Hash).count
times.times { I18n.translate('greeting', values) }
count_after = ObjectSpace.each_object(Hash).count
GC.enable

# It looks like I18n.translate by default allocates 2 new hashes
# per call. So substract it from the count.
created_due_to_globals = count_after - count_before - times * 2

assert_equal created_due_to_globals, 0
end
end

0 comments on commit 6ff3101

Please sign in to comment.