From 3a953eb04da4822c80f04e25785c05b108c89477 Mon Sep 17 00:00:00 2001 From: Patricio de Villa Date: Wed, 20 Mar 2024 12:04:37 -0600 Subject: [PATCH] add rubocop, github actions --- .github/workflows/test.yml | 25 ++++++ .gitignore | 2 +- .rubocop-minitest.yml | 12 +++ .rubocop.yml | 47 +++++++++++ .rubocop_todo.yml | 60 ++++++++++++++ Gemfile | 18 ++++- Gemfile.lock | 46 ----------- Rakefile | 17 ++-- bin/console | 7 +- json_locale.gemspec | 53 +++++-------- lib/json_locale.rb | 78 +++++++++---------- lib/json_locale/version.rb | 4 +- ...son_locale_spec.rb => json_locale_test.rb} | 37 +++++---- test/test_helper.rb | 8 +- 14 files changed, 268 insertions(+), 146 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 .rubocop-minitest.yml create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml delete mode 100644 Gemfile.lock rename test/spec/{json_locale_spec.rb => json_locale_test.rb} (88%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b90d526 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,25 @@ +name: Test + +on: [pull_request] + +# permissions: +# contents: read + +jobs: + lint: + runs-on: ubuntu-latest + # env: + # BUNDLE_ONLY: rubocop + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby 3.2.2 + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.2.2 + bundler-cache: true + + - name: Run Tests + run: bundle exec rake + # run: bundle exec rubocop --parallel \ No newline at end of file diff --git a/.gitignore b/.gitignore index c14216a..1f8fbb9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ /pkg/ /spec/reports/ /tmp/ -.byebug_history \ No newline at end of file +Gemfile.lock \ No newline at end of file diff --git a/.rubocop-minitest.yml b/.rubocop-minitest.yml new file mode 100644 index 0000000..aea76a5 --- /dev/null +++ b/.rubocop-minitest.yml @@ -0,0 +1,12 @@ +########################################################### +#################### Rubocop Minitest ##################### +########################################################### + +Minitest/AssertTruthy: + Enabled: false + +Minitest/RefuteFalse: + Enabled: false + +Minitest/MultipleAssertions: + Max: 4 \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..d5a1df6 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,47 @@ +# see example at https://gist.github.com/jhass/a5ae80d87f18e53e7b56 + +# <% unless ENV['BYPASS_RUBOCOP_TODO'] %> +# inherit_from: +# <% else %> +# inherit_from: +# - '.rubocop-todo.yml' +# <% end %> + +inherit_from: + - .rubocop_todo.yml + - .rubocop-minitest.yml + +require: + - rubocop-minitest + - rubocop-rake + - rubocop-performance + +AllCops: + NewCops: enable + # TargetRubyVersion: 2.7.8 + # TargetRailsVersion: 6.1.4 + # Exclude: + # - 'Gemfile.lock' + +Naming/VariableNumber: + Enabled: false + +Layout/SpaceInsideHashLiteralBraces: + Enabled: false + +Style/FrozenStringLiteralComment: + Enabled: false + +Layout/EmptyLinesAroundModuleBody: + EnforcedStyle: empty_lines_special + Enabled: false + +Layout/TrailingEmptyLines: + Enabled: false + EnforcedStyle: final_blank_line + +Layout/EmptyLinesAroundClassBody: + Enabled: false + +Style/RaiseArgs: + EnforcedStyle: compact \ No newline at end of file diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..727a638 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,60 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2024-03-20 18:00:51 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 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 46 + +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 11 + +# Offense count: 3 +# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Exclude: + - 'test/spec/super_hash/utils_spec.rb' + - 'lib/json_locale.rb' + - 'test/spec/json_locale_test.rb' + +# Offense count: 1 +# Configuration parameters: CountKeywordArgs, MaxOptionalParameters. +Metrics/ParameterLists: + Max: 7 + +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 11 + +# Offense count: 3 +# Configuration parameters: Max. +Minitest/MultipleAssertions: + Exclude: + - 'test/spec/json_locale_test.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# AllowedMethods: lambda, proc, it +Style/BlockDelimiters: + Exclude: + - 'test/spec/json_locale_test.rb' + +# Offense count: 3 +# Configuration parameters: AllowedConstants. +Style/Documentation: + Exclude: + - 'spec/**/*' + - 'test/**/*' + - 'lib/json_locale.rb' diff --git a/Gemfile b/Gemfile index c79ec5e..83cfa9c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,20 @@ -source "https://rubygems.org" +# frozen_string_literal: true -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } +source 'https://rubygems.org' + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } # Specify your gem's dependencies in json_locale.gemspec gemspec + +# gem 'bundler', '2.4.22' +gem 'debug', '>= 1.0.0' +gem 'minitest', '~> 5.14' +gem 'minitest-reporters', '~> 1.6' +gem 'rake', '~> 13.1' + +# rubocop +gem 'rubocop', '~> 1.62' +gem 'rubocop-minitest', '~> 0.35' +gem 'rubocop-performance', '~> 1.20' +gem 'rubocop-rake', '~> 0.6' diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 41f5cd4..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,46 +0,0 @@ -PATH - remote: . - specs: - json_locale (0.2.0) - -GEM - remote: https://rubygems.org/ - specs: - ansi (1.5.0) - builder (3.2.4) - debug (1.8.0) - irb (>= 1.5.0) - reline (>= 0.3.1) - io-console (0.6.0) - irb (1.9.1) - rdoc - reline (>= 0.3.8) - minitest (5.14.4) - minitest-reporters (1.6.1) - ansi - builder - minitest (>= 5.0) - ruby-progressbar - psych (5.1.1.1) - stringio - rake (13.1.0) - rdoc (6.6.0) - psych (>= 4.0.0) - reline (0.4.1) - io-console (~> 0.5) - ruby-progressbar (1.13.0) - stringio (3.1.0) - -PLATFORMS - ruby - -DEPENDENCIES - bundler (= 2.4.22) - debug (>= 1.0.0) - json_locale! - minitest (~> 5.14) - minitest-reporters (~> 1.6) - rake (~> 13.1) - -BUNDLED WITH - 2.4.22 diff --git a/Rakefile b/Rakefile index bb764f6..b458baa 100644 --- a/Rakefile +++ b/Rakefile @@ -1,10 +1,17 @@ -require "bundler/gem_tasks" -require "rake/testtask" +# frozen_string_literal: true + +require 'bundler/gem_tasks' +require 'rake/testtask' Rake::TestTask.new do |t| - t.libs << "test" - t.test_files = FileList["test/**/*_spec.rb"] t.verbose = true + t.warning = true + t.libs << 'test' + t.libs << 'lib' + t.test_files = FileList['test/**/*_test.rb'] end -task :default => :test \ No newline at end of file +require 'rubocop/rake_task' +RuboCop::RakeTask.new + +task default: %i[test rubocop] diff --git a/bin/console b/bin/console index 542163b..df8feb3 100755 --- a/bin/console +++ b/bin/console @@ -1,7 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true -require "bundler/setup" -require "json_locale" +require 'bundler/setup' +require 'json_locale' # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. @@ -10,5 +11,5 @@ require "json_locale" # require "pry" # Pry.start -require "irb" +require 'irb' IRB.start(__FILE__) diff --git a/json_locale.gemspec b/json_locale.gemspec index 7ea132d..7f38c47 100644 --- a/json_locale.gemspec +++ b/json_locale.gemspec @@ -1,44 +1,33 @@ +# frozen_string_literal: true -lib = File.expand_path("../lib", __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "json_locale/version" +require_relative 'lib/json_locale/version' Gem::Specification.new do |spec| - spec.name = "json_locale" + spec.name = 'json_locale' spec.version = JsonLocale::VERSION - spec.authors = ["Pato"] - spec.email = ["pato_devilla@hotmail.com"] + spec.authors = ['Pato'] + spec.email = ['pato_devilla@hotmail.com'] - spec.summary = %q{Save translated data on jsons} - spec.description = %q{Save translated data on jsons} + spec.summary = 'Save translated data on jsons' + spec.description = 'Save translated data on jsons' # spec.homepage = "TODO: Put your gem's website or public repo URL here." + spec.license = 'MIT' + spec.required_ruby_version = '>= 3.1.0' - # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' - # to allow pushing to a single host or delete this section to allow pushing to any host. - # if spec.respond_to?(:metadata) - # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" - - # spec.metadata["homepage_uri"] = spec.homepage - # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." - # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." - # else - # raise "RubyGems 2.0 or newer is required to protect against " \ - # "public gem pushes." - # end + # spec.metadata["homepage_uri"] = spec.homepage + # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." + # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." + spec.metadata['rubygems_mfa_required'] = 'true' # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + spec.files = Dir.chdir(__dir__) do + `git ls-files -z`.split("\x0").reject do |f| + (File.expand_path(f) == __FILE__) || + f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile]) + end end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler", "2.4.22" - spec.add_development_dependency "rake", "~> 13.1" - spec.add_development_dependency "debug", ">= 1.0.0" - spec.add_development_dependency "minitest", "~> 5.14" - spec.add_development_dependency "minitest-reporters", "~> 1.6" - + spec.bindir = 'exe' + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } + spec.require_paths = ['lib'] end diff --git a/lib/json_locale.rb b/lib/json_locale.rb index ac05d7c..0fc0e9f 100644 --- a/lib/json_locale.rb +++ b/lib/json_locale.rb @@ -1,8 +1,9 @@ -require "json_locale/version" +# frozen_string_literal: true + +require 'json_locale/version' module JsonLocale module Translates - def self.included(base) base.extend ClassMethods base.include InstanceMethods @@ -16,15 +17,14 @@ def self.included(base) @allow_blank = false @fallback = false @set_missing_accessor = false - - class << self + class << self # @return [Array] attr_accessor :available_locales - + # @return [nil,Proc] called before setting the value, can be used for dirtiness attr_accessor :before_set - + # @return [nil,Proc,String] attr_accessor :default_locale @@ -39,17 +39,15 @@ class << self # @return [Boolean] attr_accessor :set_missing_accessor - + # Allows gem configuration - def configure(&block) + def configure yield self end - end module ClassMethods - - NORMALIZE_LOCALE_PROC = Proc.new do |locale| + NORMALIZE_LOCALE_PROC = proc do |locale| locale.downcase.gsub(/[^a-z]/, '') end @@ -57,7 +55,7 @@ module ClassMethods def inherited(klass) super - klass.instance_variable_set('@translatable_attributes', self.translatable_attributes.dup) + klass.instance_variable_set(:@translatable_attributes, translatable_attributes.dup) end # Adds convinience methods used for managing translations on a json type attribute @@ -68,7 +66,7 @@ def inherited(klass) # include JsonLocale::Translates # translates :name_translations, {} # end - # + # # Available instance methods: # # - instance.name @@ -90,14 +88,15 @@ def inherited(klass) # @param [false, :any, Array] fallback # @param [Boolean] set_missing_accessor, if true defines accessor from attr_name param # @return [void] - def translates(attr_name, - before_set: JsonLocale::Translates.before_set, - default_locale: JsonLocale::Translates.default_locale, - suffix: JsonLocale::Translates.suffix, - allow_blank: JsonLocale::Translates.allow_blank, - fallback: JsonLocale::Translates.fallback, - set_missing_accessor: JsonLocale::Translates.set_missing_accessor - ) + def translates( + attr_name, + before_set: JsonLocale::Translates.before_set, + default_locale: JsonLocale::Translates.default_locale, + suffix: JsonLocale::Translates.suffix, + allow_blank: JsonLocale::Translates.allow_blank, + fallback: JsonLocale::Translates.fallback, + set_missing_accessor: JsonLocale::Translates.set_missing_accessor + ) attr_name = attr_name.to_s @@ -107,17 +106,15 @@ def translates(attr_name, if @translatable_attributes.nil? @translatable_attributes = [] - else - if @translatable_attributes.include?(attr_name) - raise StandardError.new("#{attr_name} translation has already been registered") - end + elsif @translatable_attributes.include?(attr_name) + raise StandardError.new("#{attr_name} translation has already been registered") end if set_missing_accessor - attr_reader attr_name unless self.instance_methods.include? attr_name - attr_writer attr_name unless self.instance_methods.include? "#{attr_name}=" + attr_reader attr_name unless instance_methods.include? attr_name + attr_writer attr_name unless instance_methods.include? "#{attr_name}=" end - + @translatable_attributes.push attr_name attr_without_suffix = attr_name.sub(suffix, '') @@ -134,10 +131,10 @@ def translates(attr_name, # define locale agnostic setter define_method :"set_#{attr_name}" do |value, **params| - value.each do |locale, value| + value.each do |locale, val| write_json_translation( attr_name, - value, + val, locale: NORMALIZE_LOCALE_PROC.call(locale.to_s), allow_blank: params.fetch(:allow_blank, allow_blank), before_set: params.fetch(:before_set, before_set) @@ -169,20 +166,16 @@ def translates(attr_name, before_set: params.fetch(:before_set, before_set) ) end - end - end # @return [Boolean] true if the class supports attribute translation def translates? included_modules.include?(InstanceMethods) end - end module InstanceMethods - private # Sets a value for a specific locale @@ -195,7 +188,9 @@ module InstanceMethods # @return [void] def write_json_translation(attr_name, value, locale:, allow_blank:, before_set:) locale = locale&.to_s - raise StandardError.new("invalid locale #{locale}") unless JsonLocale::Translates.available_locales.map(&:to_s).include?(locale) + unless JsonLocale::Translates.available_locales.map(&:to_s).include?(locale) + raise StandardError.new("invalid locale #{locale}") + end translations = public_send(attr_name) || {} @@ -207,7 +202,7 @@ def write_json_translation(attr_name, value, locale:, allow_blank:, before_set:) translations[locale] = value end - public_send("#{attr_name}=", translations) + public_send(:"#{attr_name}=", translations) end # Get a value for a specific locale @@ -218,7 +213,10 @@ def write_json_translation(attr_name, value, locale:, allow_blank:, before_set:) # @return [String] the value of the specified locale def read_json_translation(attr_name, locale:, fallback:) locale = locale&.to_s - raise StandardError.new("invalid locale #{locale}") unless JsonLocale::Translates.available_locales.map(&:to_s).include?(locale) + unless JsonLocale::Translates.available_locales.map(&:to_s).include?(locale) + raise StandardError.new("invalid locale #{locale}") + end + translations = public_send(attr_name) || {} if translations.key?(locale) @@ -226,15 +224,13 @@ def read_json_translation(attr_name, locale:, fallback:) else case fallback when :any - translations.find{|k,v| !v.nil?}.try(:[], 1) + translations.find { |_k, v| !v.nil? }.try(:[], 1) when Array - locale = fallback.find{|locale| !translations[locale].nil?} + locale = fallback.find { |locale| !translations[locale].nil? } locale.nil? ? nil : translations[locale] end end end - end - end end diff --git a/lib/json_locale/version.rb b/lib/json_locale/version.rb index c99b40a..1ade8de 100644 --- a/lib/json_locale/version.rb +++ b/lib/json_locale/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JsonLocale - VERSION = "0.2.0" + VERSION = '0.2.1' end diff --git a/test/spec/json_locale_spec.rb b/test/spec/json_locale_test.rb similarity index 88% rename from test/spec/json_locale_spec.rb rename to test/spec/json_locale_test.rb index d9f6d1d..ac97ab2 100644 --- a/test/spec/json_locale_spec.rb +++ b/test/spec/json_locale_test.rb @@ -1,13 +1,14 @@ -require "test_helper" +# frozen_string_literal: true -class ClassTest < Minitest::Test +require 'test_helper' +class JsonLocaleTest < Minitest::Test def setup JsonLocale::Translates.set_missing_accessor = true @klass = Class.new @klass.include JsonLocale::Translates - Object.const_set('Klass', @klass) + Object.const_set(:Klass, @klass) end def teardown @@ -31,7 +32,7 @@ def test_configure JsonLocale::Translates.configure do |config| config.default_locale = 'en' config.available_locales = ['en'] - config.before_set = Proc.new{} + config.before_set = proc {} end assert_equal 'en', JsonLocale::Translates.default_locale @@ -45,66 +46,74 @@ def test_translates? def test_can_add_translatable_attributes assert_nil @klass.translatable_attributes - + @klass.translates :name_translations + assert_equal 1, @klass.translatable_attributes.size assert_equal 'name_translations', @klass.translatable_attributes.first @klass.translates :title_translations + assert_equal 2, @klass.translatable_attributes.size end def test_raises_error_on_duplicate_translations @klass.translates :name_translations - assert_raises(StandardError){ @klass.translates :name_translations } + assert_raises(StandardError) { @klass.translates :name_translations } end def test_raises_error_with_invalid_suffix - assert_raises(StandardError){ + assert_raises(StandardError) { @klass.translates :name_translations, suffix: '_i18n' } end def test_setters JsonLocale::Translates.configure do |config| - config.available_locales = ['es', 'en'] + config.available_locales = %w[es en] end @klass.translates :name_translations @klass.translates :title_i18n, suffix: '_i18n', allow_blank: true record = @klass.new - + # single language record.set_name_es('Prueba') + assert_equal 'Prueba', record.name_translations['es'] record.set_name_en('Test') + assert_equal 'Test', record.name_translations['en'] # bulk setter - record.set_name_translations({es: 'Canadá', en: 'Canada'}) + record.set_name_translations({ es: 'Canadá', en: 'Canada' }) + assert_equal 'Canadá', record.name_translations['es'] assert_equal 'Canada', record.name_translations['en'] # allow_blank param when true record.set_name_es('') record.set_name_en(nil) + assert_equal false, record.name_translations.key?('es') assert_equal false, record.name_translations.key?('en') # allow_blank override record.set_name_es('', allow_blank: true) + assert_equal '', record.name_translations['es'] # allow_blank param when false record.set_title_es('') record.set_title_en(nil) + assert_equal '', record.title_i18n['es'] assert_nil record.title_i18n['en'] end def test_getters JsonLocale::Translates.configure do |config| - config.available_locales = ['es', 'en', 'de'] + config.available_locales = %w[es en de] end @klass.translates :name_translations, fallback: false @@ -113,18 +122,20 @@ def test_getters # getters record.set_name_es('Prueba') + assert_equal 'Prueba', record.name_es assert_equal 'Prueba', record.name(locale: 'es') record.set_name_en('Test') + assert_equal 'Test', record.name_en # default fallback record.set_title_es('Prueba') + assert_equal 'Prueba', record.title_en # override fallback assert_equal 'Test', record.name_de(fallback: ['en']) end - -end \ No newline at end of file +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 302d1dd..7429725 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,7 +1,11 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift File.expand_path('../lib', __dir__) +require 'json_locale' +require 'debug' + require 'minitest/autorun' require 'minitest/spec' require 'minitest/reporters' -require 'json_locale' -require 'debug' Minitest::Reporters.use!