Skip to content

Commit

Permalink
Make i18n dependency optional
Browse files Browse the repository at this point in the history
  • Loading branch information
peterfication committed Jan 8, 2024
1 parent 989f1f8 commit c888587
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 19 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,10 @@ jobs:
- run: bundle install --jobs=3 --retry=3 --path=vendor/bundle
- run: bundle exec rake spec
continue-on-error: ${{ matrix.entry.allowed-failure }}
- name: Specs for when the i18n gem is not available
run: |
cd spec_i18n
bundle install --jobs=3 --retry=3
pwd
bundle exec rake spec
continue-on-error: ${{ matrix.entry.allowed-failure }}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### 1.0.0 (Next)

* [#41](https://github.com/dblock/ruby-enum/pull/41): Make i18n dependency optional - [@peterfication](https://github.com/peterfication).
* [#43](https://github.com/dblock/ruby-enum/pull/43): Add exhaustive case matcher - [@peterfication](https://github.com/peterfication).
* [#40](https://github.com/dblock/ruby-enum/pull/39): Enable new Rubocop cops and address/allowlist lints - [@petergoldstein](https://github.com/petergoldstein).
* [#39](https://github.com/dblock/ruby-enum/pull/39): Require Ruby >= 2.7 - [@petergoldstein](https://github.com/petergoldstein).
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Enum-like behavior for Ruby, heavily inspired by [this](http://www.rubyfleebie.c
- [Duplicate enumerator keys or duplicate values](#duplicate-enumerator-keys-or-duplicate-values)
- [Inheritance](#inheritance)
- [Exhaustive case matcher](#exhaustive-case-matcher)
- [I18n support](#i18n-support)
- [Benchmarks](#benchmarks)
- [Contributing](#contributing)
- [Copyright and License](#copyright-and-license)
Expand Down Expand Up @@ -300,6 +301,15 @@ Color.Case(color, {
})
```

### I18n support

This gem has an optional dependency to `i18n`. If it's available, the error messages will have a nice description and can be translated. If it's not available, the errors will only contain the message keys.

```ruby
# Add this to your Gemfile if you want to have a nice error description instead of just a message key.
gem "i18n"
```

## Benchmarks

Benchmark scripts are defined in the [`benchmarks`](benchmarks) folder and can be run with Rake:
Expand Down
17 changes: 14 additions & 3 deletions lib/ruby-enum.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
# frozen_string_literal: true

require 'i18n'

require 'ruby-enum/version'
require 'ruby-enum/enum'
require 'ruby-enum/enum/case'
require 'ruby-enum/enum/i18n_mock'

# Try to load the I18n gem and provide a mock if it is not available.
begin
require 'i18n'
Ruby::Enum.i18n = I18n
rescue LoadError
# I18n is not available
# :nocov:
# Tests for this loading are in the spec_i18n folder
Ruby::Enum.i18n = Ruby::Enum::I18nMock
# :nocov:
end

I18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
Ruby::Enum.i18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')

require 'ruby-enum/errors/base'
require 'ruby-enum/errors/uninitialized_constant_error'
Expand Down
5 changes: 5 additions & 0 deletions lib/ruby-enum/enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

module Ruby
module Enum
class << self
# Needed for I18n mock
attr_accessor :i18n
end

attr_reader :key, :value

def initialize(key, value)
Expand Down
19 changes: 19 additions & 0 deletions lib/ruby-enum/enum/i18n_mock.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

# :nocov:
module Ruby
module Enum
##
# Mock I18n module in case the i18n gem is not available.
module I18nMock
def self.load_path
[]
end

def self.translate(key, _options = {})
key
end
end
end
end
# :nocov:
2 changes: 1 addition & 1 deletion lib/ruby-enum/errors/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def compose_message(key, attributes = {})
#
# Returns a localized error message string.
def translate(key, options)
::I18n.translate("#{BASE_KEY}.#{key}", locale: :en, **options).strip
Ruby::Enum.i18n.translate("#{BASE_KEY}.#{key}", locale: :en, **options).strip
end

# Create the problem.
Expand Down
1 change: 0 additions & 1 deletion ruby-enum.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ Gem::Specification.new do |s|
s.homepage = 'http://github.com/dblock/ruby-enum'
s.licenses = ['MIT']
s.summary = 'Enum-like behavior for Ruby.'
s.add_dependency 'i18n'
s.metadata['rubygems_mfa_required'] = 'true'
end
76 changes: 62 additions & 14 deletions spec/ruby-enum/enum_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,24 @@ class SecondSubclass < FirstSubclass
expect(Colors::GREEN).to eq 'green'
end

it 'raises UninitializedConstantError on an invalid constant' do
expect { Colors::ANYTHING }.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /The constant Colors::ANYTHING has not been defined./
context 'when the i18n gem is loaded' do
it 'raises UninitializedConstantError on an invalid constant' do
expect do
Colors::ANYTHING
end.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /The constant Colors::ANYTHING has not been defined./
end
end

context 'when the i18n gem is not loaded' do
before do
allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
end

it 'raises UninitializedConstantError on an invalid constant' do
expect do
Colors::ANYTHING
end.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /ruby.enum.errors.messages.uninitialized_constant.summary/
end
end

describe '#each' do
Expand Down Expand Up @@ -151,22 +167,54 @@ class SecondSubclass < FirstSubclass
end

context 'when a duplicate key is used' do
it 'raises DuplicateKeyError' do
expect do
Colors.class_eval do
define :RED, 'some'
end
end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /The constant Colors::RED has already been defined./
context 'when the i18n gem is loaded' do
it 'raises DuplicateKeyError' do
expect do
Colors.class_eval do
define :RED, 'some'
end
end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /The constant Colors::RED has already been defined./
end
end

context 'when the i18n gem is not loaded' do
before do
allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
end

it 'raises DuplicateKeyError' do
expect do
Colors.class_eval do
define :RED, 'some'
end
end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /ruby.enum.errors.messages.duplicate_key.message/
end
end
end

context 'when a duplicate value is used' do
it 'raises a DuplicateValueError' do
expect do
Colors.class_eval do
define :Other, 'red'
end
end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /The value red has already been defined./
context 'when the i18n gem is loaded' do
it 'raises a DuplicateValueError' do
expect do
Colors.class_eval do
define :Other, 'red'
end
end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /The value red has already been defined./
end
end

context 'when the i18n gem is not loaded' do
before do
allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
end

it 'raises a DuplicateValueError' do
expect do
Colors.class_eval do
define :Other, 'red'
end
end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /ruby.enum.errors.messages.duplicate_value.summary/
end
end
end

Expand Down
9 changes: 9 additions & 0 deletions spec_i18n/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

source 'http://rubygems.org'

gemspec path: '../', name: 'ruby-enum'

# This Gemfile should not include any gem that has i18n as a dependency.
gem 'rake'
gem 'rspec', '~> 3.0'
12 changes: 12 additions & 0 deletions spec_i18n/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

require 'rubygems'

require 'rspec/core'
require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
end

task default: %i[spec]
52 changes: 52 additions & 0 deletions spec_i18n/spec/i18n_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

require 'spec_helper'

test_class = Class.new do
include Ruby::Enum

define :RED, 'red'
define :GREEN, 'green'
end

describe Ruby::Enum do
context 'when the i18n gem is not loaded' do
it 'raises UninitializedConstantError on an invalid constant' do
expect do
test_class::ANYTHING
end.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /ruby.enum.errors.messages.uninitialized_constant.summary/
end
end

context 'when a duplicate key is used' do
context 'when the i18n gem is not loaded' do
before do
allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
end

it 'raises DuplicateKeyError' do
expect do
test_class.class_eval do
define :RED, 'some'
end
end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /ruby.enum.errors.messages.duplicate_key.message/
end
end
end

context 'when a duplicate value is used' do
context 'when the i18n gem is not loaded' do
before do
allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
end

it 'raises a DuplicateValueError' do
expect do
test_class.class_eval do
define :Other, 'red'
end
end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /ruby.enum.errors.messages.duplicate_value.summary/
end
end
end
end
8 changes: 8 additions & 0 deletions spec_i18n/spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib'))

require 'rubygems'

require 'rspec'
require 'ruby-enum'

0 comments on commit c888587

Please sign in to comment.