Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fallback_on_presence, fixes, more test cases #3

Merged
merged 1 commit into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require:

AllCops:
NewCops: enable
# TargetRubyVersion: 2.7.8
TargetRubyVersion: 3.2.2
# TargetRailsVersion: 6.1.4
# Exclude:
# - 'Gemfile.lock'
Expand Down
35 changes: 22 additions & 13 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,49 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2024-03-20 18:00:51 UTC using RuboCop version 1.62.1.
# on 2024-04-25 19:10:42 UTC using RuboCop version 1.62.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 6
# Offense count: 1
# Configuration parameters: Severity, Include.
# Include: **/*.gemspec
Gemspec/RequiredRubyVersion:
Exclude:
- 'json_locale.gemspec'

# Offense count: 9
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 46
Max: 48

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Max: 221

# Offense count: 3
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity:
Max: 11
Max: 10

# Offense count: 3
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
# Offense count: 10
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Exclude:
- 'test/spec/super_hash/utils_spec.rb'
- 'lib/json_locale.rb'
- 'test/spec/json_locale_test.rb'
Max: 56

# Offense count: 1
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
Metrics/ParameterLists:
Max: 7
Max: 8

# Offense count: 3
# Offense count: 2
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/PerceivedComplexity:
Max: 11

# Offense count: 3
# Offense count: 6
# Configuration parameters: Max.
Minitest/MultipleAssertions:
Exclude:
Expand Down
83 changes: 58 additions & 25 deletions lib/json_locale.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@ def self.included(base)
base.include InstanceMethods
end

# default configuration
@available_locales = []
@before_set = nil
@default_locale = nil
@suffix = '_translations'
@allow_blank = false
@fallback = false
@set_missing_accessor = false

class << self
# @return [Array<Symbol>]
attr_accessor :available_locales
Expand All @@ -40,12 +31,30 @@ class << self
# @return [Boolean]
attr_accessor :set_missing_accessor

# @return [Boolean]
attr_accessor :fallback_on_presence

# Allows gem configuration
def configure
yield self
end

# default configuration
def reset_configuration!
@available_locales = []
@before_set = nil
@default_locale = nil
@suffix = '_translations'
@allow_blank = false
@fallback = false
@set_missing_accessor = false
@fallback_on_presence = true
end

end

reset_configuration!

module ClassMethods
NORMALIZE_LOCALE_PROC = proc do |locale|
locale.downcase.gsub(/[^a-z]/, '')
Expand Down Expand Up @@ -87,6 +96,7 @@ def inherited(klass)
# @param [Boolean] allow_blank
# @param [false, :any, Array<String>] fallback
# @param [Boolean] set_missing_accessor, if true defines accessor from attr_name param
# @param [Boolean] fallback_on_presence
# @return [void]
def translates(
attr_name,
Expand All @@ -95,7 +105,8 @@ def translates(
suffix: JsonLocale::Translates.suffix,
allow_blank: JsonLocale::Translates.allow_blank,
fallback: JsonLocale::Translates.fallback,
set_missing_accessor: JsonLocale::Translates.set_missing_accessor
set_missing_accessor: JsonLocale::Translates.set_missing_accessor,
fallback_on_presence: JsonLocale::Translates.fallback_on_presence
)

attr_name = attr_name.to_s
Expand All @@ -121,11 +132,13 @@ def translates(

# define locale agnostic getter
define_method :"#{attr_without_suffix}" do |**params|
locale = default_locale.call if default_locale.is_a?(Proc) # careful not to override default_locale variable
# careful not to override default_locale variable
locale = default_locale.is_a?(Proc) ? default_locale.call : default_locale
read_json_translation(
attr_name,
locale: params.fetch(:locale, locale),
fallback: params.fetch(:fallback, fallback)
fallback: params.fetch(:fallback, fallback),
fallback_on_presence: params.fetch(:fallback_on_presence, fallback_on_presence)
)
end

Expand All @@ -152,7 +165,8 @@ def translates(
read_json_translation(
attr_name,
locale: normalized_locale,
fallback: params.fetch(:fallback, fallback)
fallback: params.fetch(:fallback, fallback),
fallback_on_presence: params.fetch(:fallback_on_presence, fallback_on_presence)
)
end

Expand Down Expand Up @@ -183,7 +197,7 @@ module InstanceMethods
# @param [Symbol] attr_name
# @param [String] value
# @param [Symbol] locale
# @param [Boolean] allow_blank if true and value is nil or '', the key will be deleted
# @param [Boolean] allow_blank if fakse and value is nil or '', the key will be deleted
# @param [Proc] before_set
# @return [void]
def write_json_translation(attr_name, value, locale:, allow_blank:, before_set:)
Expand All @@ -210,25 +224,44 @@ def write_json_translation(attr_name, value, locale:, allow_blank:, before_set:)
# @param [Symbol] attr_name
# @param [Symbol] locale
# @param [false, :any, Array<Symbol>] fallback if Array, values must be locales
# @param [Boolean] fallback_on_presence
# @return [String] the value of the specified locale
def read_json_translation(attr_name, locale:, fallback:)
def read_json_translation(attr_name, locale:, fallback:, fallback_on_presence:)
locale = locale&.to_s
unless JsonLocale::Translates.available_locales.map(&:to_s).include?(locale)
raise StandardError.new("invalid locale #{locale}")
end

translations = public_send(attr_name) || {}
translations = public_send(attr_name)
return unless translations

if translations.key?(locale)
translations[locale]
value = translations[locale]
return value if matches?(translations, locale, fallback_on_presence:)

case fallback
when :any, true
fallback(translations.except(locale), fallback_on_presence:)
when String
translations[fallback]
when Array
fallback(translations.slice(*fallback), fallback_on_presence:)
end
end

# @return [NilClass|String]
def fallback(translations, **)
translations.find do |locale, _value|
matches?(translations, locale, **)
end&.last
end

# @return [Boolean]
def matches?(translations, locale, fallback_on_presence:)
if fallback_on_presence
value = translations[locale]
!value.nil? && value != ''
else
case fallback
when :any
translations.find { |_k, v| !v.nil? }.try(:[], 1)
when Array
locale = fallback.find { |locale| !translations[locale].nil? }
locale.nil? ? nil : translations[locale]
end
translations.key?(locale)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/json_locale/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module JsonLocale
VERSION = '0.2.1'
VERSION = '0.2.2'
end
Loading