loading
Generated 2021-01-31T14:34:10-05:00

All Files ( 100.0% covered at 3.01 hits/line )

7 files in total.
119 relevant lines, 119 lines covered and 0 lines missed. ( 100.0% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line
lib/ruby-enum.rb 100.00 % 13 8 8 0 1.00
lib/ruby-enum/enum.rb 100.00 % 171 67 67 0 3.91
lib/ruby-enum/errors/base.rb 100.00 % 80 22 22 0 2.91
lib/ruby-enum/errors/duplicate_key_error.rb 100.00 % 14 6 6 0 1.00
lib/ruby-enum/errors/duplicate_value_error.rb 100.00 % 14 6 6 0 1.00
lib/ruby-enum/errors/uninitialized_constant_error.rb 100.00 % 13 6 6 0 1.33
spec/ruby-enum/version_spec.rb 100.00 % 9 4 4 0 1.00

lib/ruby-enum.rb

100.0% lines covered

8 relevant lines. 8 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'i18n'
  3. 1 require 'ruby-enum/version'
  4. 1 require 'ruby-enum/enum'
  5. 1 I18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
  6. 1 require 'ruby-enum/errors/base'
  7. 1 require 'ruby-enum/errors/uninitialized_constant_error'
  8. 1 require 'ruby-enum/errors/duplicate_key_error'
  9. 1 require 'ruby-enum/errors/duplicate_value_error'

lib/ruby-enum/enum.rb

100.0% lines covered

67 relevant lines. 67 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Ruby
  3. 1 module Enum
  4. 1 attr_reader :key, :value
  5. 1 def initialize(key, value)
  6. 8 @key = key
  7. 8 @value = value
  8. end
  9. 1 def self.included(base)
  10. 4 base.extend Enumerable
  11. 4 base.extend ClassMethods
  12. 4 base.private_class_method(:new)
  13. end
  14. 1 module ClassMethods
  15. # Define an enumerated value.
  16. #
  17. # === Parameters
  18. # [key] Enumerator key.
  19. # [value] Enumerator value.
  20. 1 def define(key, value = key)
  21. 10 @_enum_hash ||= {}
  22. 10 @_enums_by_value ||= {}
  23. 10 validate_key!(key)
  24. 9 validate_value!(value)
  25. 8 store_new_instance(key, value)
  26. 8 if upper?(key.to_s)
  27. 5 const_set key, value
  28. else
  29. 6 define_singleton_method(key) { value }
  30. end
  31. end
  32. 1 def store_new_instance(key, value)
  33. 8 new_instance = new(key, value)
  34. 8 @_enum_hash[key] = new_instance
  35. 8 @_enums_by_value[value] = new_instance
  36. end
  37. 1 def const_missing(key)
  38. 3 raise Ruby::Enum::Errors::UninitializedConstantError, name: name, key: key
  39. end
  40. # Iterate over all enumerated values.
  41. # Required for Enumerable mixin
  42. 1 def each(&block)
  43. 8 @_enum_hash.each(&block)
  44. end
  45. # Attempt to parse an enum key and return the
  46. # corresponding value.
  47. #
  48. # === Parameters
  49. # [k] The key string to parse.
  50. #
  51. # Returns the corresponding value or nil.
  52. 1 def parse(k)
  53. 4 k = k.to_s.upcase
  54. 4 each do |key, enum|
  55. 6 return enum.value if key.to_s.upcase == k
  56. end
  57. nil
  58. end
  59. # Whether the specified key exists in this enum.
  60. #
  61. # === Parameters
  62. # [k] The string key to check.
  63. #
  64. # Returns true if the key exists, false otherwise.
  65. 1 def key?(k)
  66. 7 @_enum_hash.key?(k)
  67. end
  68. # Gets the string value for the specified key.
  69. #
  70. # === Parameters
  71. # [k] The key symbol to get the value for.
  72. #
  73. # Returns the corresponding enum instance or nil.
  74. 1 def value(k)
  75. 5 enum = @_enum_hash[k]
  76. 5 enum&.value
  77. end
  78. # Whether the specified value exists in this enum.
  79. #
  80. # === Parameters
  81. # [k] The string value to check.
  82. #
  83. # Returns true if the value exists, false otherwise.
  84. 1 def value?(v)
  85. 7 @_enums_by_value.key?(v)
  86. end
  87. # Gets the key symbol for the specified value.
  88. #
  89. # === Parameters
  90. # [v] The string value to parse.
  91. #
  92. # Returns the corresponding key symbol or nil.
  93. 1 def key(v)
  94. 5 enum = @_enums_by_value[v]
  95. 5 enum&.key
  96. end
  97. # Returns all enum keys.
  98. 1 def keys
  99. 2 @_enum_hash.values.map(&:key)
  100. end
  101. # Returns all enum values.
  102. 1 def values
  103. 7 result = @_enum_hash.values.map(&:value)
  104. 7 if superclass < Ruby::Enum
  105. 3 superclass.values + result
  106. else
  107. 4 result
  108. end
  109. end
  110. # Iterate over all enumerated values.
  111. # Required for Enumerable mixin
  112. 1 def each_value(&_block)
  113. 1 @_enum_hash.each_value do |v|
  114. 2 yield v.value
  115. end
  116. end
  117. # Iterate over all enumerated keys.
  118. # Required for Enumerable mixin
  119. 1 def each_key(&_block)
  120. 1 @_enum_hash.each_value do |v|
  121. 2 yield v.key
  122. end
  123. end
  124. 1 def to_h
  125. 1 Hash[@_enum_hash.map do |key, enum|
  126. 2 [key, enum.value]
  127. end]
  128. end
  129. 1 private
  130. 1 def upper?(s)
  131. 8 !/[[:upper:]]/.match(s).nil?
  132. end
  133. 1 def validate_key!(key)
  134. 10 return unless @_enum_hash.key?(key)
  135. 1 raise Ruby::Enum::Errors::DuplicateKeyError, name: name, key: key
  136. end
  137. 1 def validate_value!(value)
  138. 9 return unless @_enums_by_value.key?(value)
  139. 1 raise Ruby::Enum::Errors::DuplicateValueError, name: name, value: value
  140. end
  141. end
  142. end
  143. end

lib/ruby-enum/errors/base.rb

100.0% lines covered

22 relevant lines. 22 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Ruby
  3. 1 module Enum
  4. 1 module Errors
  5. 1 class Base < StandardError
  6. # Problem occurred.
  7. 1 attr_reader :problem
  8. # Summary of the problem.
  9. 1 attr_reader :summary
  10. # Suggested problem resolution.
  11. 1 attr_reader :resolution
  12. # Compose the message.
  13. # === Parameters
  14. # [key] Lookup key in the translation table.
  15. # [attributes] The objects to pass to create the message.
  16. 1 def compose_message(key, attributes = {})
  17. 5 @problem = create_problem(key, attributes)
  18. 5 @summary = create_summary(key, attributes)
  19. 5 @resolution = create_resolution(key, attributes)
  20. 5 "\nProblem:\n #{@problem}"\
  21. "\nSummary:\n #{@summary}" + "\nResolution:\n #{@resolution}"
  22. end
  23. 1 private
  24. 1 BASE_KEY = 'ruby.enum.errors.messages' #:nodoc:
  25. # Given the key of the specific error and the options hash, translate the
  26. # message.
  27. #
  28. # === Parameters
  29. # [key] The key of the error in the locales.
  30. # [options] The objects to pass to create the message.
  31. #
  32. # Returns a localized error message string.
  33. 1 def translate(key, options)
  34. 15 ::I18n.translate("#{BASE_KEY}.#{key}", **{ locale: :en }.merge(options)).strip
  35. end
  36. # Create the problem.
  37. #
  38. # === Parameters
  39. # [key] The error key.
  40. # [attributes] The attributes to interpolate.
  41. #
  42. # Returns the problem.
  43. 1 def create_problem(key, attributes)
  44. 5 translate("#{key}.message", attributes)
  45. end
  46. # Create the summary.
  47. #
  48. # === Parameters
  49. # [key] The error key.
  50. # [attributes] The attributes to interpolate.
  51. #
  52. # Returns the summary.
  53. 1 def create_summary(key, attributes)
  54. 5 translate("#{key}.summary", attributes)
  55. end
  56. # Create the resolution.
  57. #
  58. # === Parameters
  59. # [key] The error key.
  60. # [attributes] The attributes to interpolate.
  61. #
  62. # Returns the resolution.
  63. 1 def create_resolution(key, attributes)
  64. 5 translate("#{key}.resolution", attributes)
  65. end
  66. end
  67. end
  68. end
  69. end

lib/ruby-enum/errors/duplicate_key_error.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Ruby
  3. 1 module Enum
  4. 1 module Errors
  5. # Error raised when a duplicate enum key is found
  6. 1 class DuplicateKeyError < Base
  7. 1 def initialize(attrs)
  8. 1 super(compose_message('duplicate_key', attrs))
  9. end
  10. end
  11. end
  12. end
  13. end

lib/ruby-enum/errors/duplicate_value_error.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Ruby
  3. 1 module Enum
  4. 1 module Errors
  5. # Error raised when a duplicate enum value is found
  6. 1 class DuplicateValueError < Base
  7. 1 def initialize(attrs)
  8. 1 super(compose_message('duplicate_value', attrs))
  9. end
  10. end
  11. end
  12. end
  13. end

lib/ruby-enum/errors/uninitialized_constant_error.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Ruby
  3. 1 module Enum
  4. 1 module Errors
  5. 1 class UninitializedConstantError < Base
  6. 1 def initialize(attrs)
  7. 3 super(compose_message('uninitialized_constant', attrs))
  8. end
  9. end
  10. end
  11. end
  12. end

spec/ruby-enum/version_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'spec_helper'
  3. 1 describe Ruby::Enum do
  4. 1 it 'has a version' do
  5. 1 expect(Ruby::Enum::VERSION).not_to be_nil
  6. end
  7. end