From 400c6256d77d3e436598dfe026244d1b260f8fe9 Mon Sep 17 00:00:00 2001 From: Rafael Soares <893971+rafasoares@users.noreply.github.com> Date: Sat, 25 May 2024 00:28:29 +0200 Subject: [PATCH] fix(deps): support Rails 7 syntax (#29) * fix(deps): support Rails 7 syntax * chore: update HumanEnum gem version to 1.1.0 * docs: :memo: document public methods * ci(deps): :construction_worker: enable test matrix for multiple Rails versions * ci(deps): :arrow_up: update actions/checkout to v4 * ci: :construction_worker: run specs and upload test coverage in the same job With the new version matrix setup, multiple uploads to the same artifact could fail, even with `overwrite: true`. --- .github/workflows/publish.yml | 2 +- .github/workflows/tests.yml | 29 ++- .ruby-version | 2 +- .vscode/settings.json | 5 + Gemfile | 22 ++- Gemfile.lock | 64 ++++--- Gemfile.rails-6.1.lock | 184 +++++++++++++++++++ Gemfile.rails-7.0.lock | 182 ++++++++++++++++++ Gemfile.rails-7.1.lock | 193 ++++++++++++++++++++ Guardfile | 8 +- README.md | 6 +- human_enum.gemspec | 4 +- lib/human_enum.rb | 77 ++++++-- lib/human_enum/version.rb | 2 +- spec/human_enum_spec.rb | 59 +++--- spec/setup_helper.rb | 2 +- spec/support/db.rb | 5 +- spec/support/locales/en.yml | 12 +- spec/support/shared/translation_examples.rb | 20 ++ spec/support/test_model.rb | 17 ++ 20 files changed, 796 insertions(+), 99 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Gemfile.rails-6.1.lock create mode 100644 Gemfile.rails-7.0.lock create mode 100644 Gemfile.rails-7.1.lock create mode 100644 spec/support/shared/translation_examples.rb create mode 100644 spec/support/test_model.rb diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cf2e028..2a08024 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,7 +21,7 @@ jobs: needs: tests steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f249ab4..686f86f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,11 +13,20 @@ jobs: name: Run specs runs-on: ubuntu-latest + strategy: + matrix: + ruby: ['3.0', '3.1', '3.2', '3.3'] + rails: ['6.1', '7.0', '7.1'] + + env: + BUNDLE_LOCKFILE: rails-${{ matrix.rails }} + steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: + ruby-version: ${{ matrix.ruby }} rubygems: latest bundler-cache: true @@ -26,24 +35,26 @@ jobs: CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} run: bin/rspec - - uses: actions/upload-artifact@v4 - with: - name: code-coverage - path: coverage - coverage: name: Report code coverage needs: test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: ruby/setup-ruby@v1 with: - name: code-coverage - path: coverage + rubygems: latest + bundler-cache: true - uses: paambaati/codeclimate-action@v6 + with: + coverageCommand: bin/rspec env: CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + + - uses: actions/upload-artifact@v4 + with: + name: code-coverage + path: coverage diff --git a/.ruby-version b/.ruby-version index aed7acb..4a85a55 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-3.2.4 +ruby-3.3.1 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..be4f468 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "conventionalCommits.scopes": [ + "deps" + ] +} diff --git a/Gemfile b/Gemfile index 9aac809..6bf1a31 100644 --- a/Gemfile +++ b/Gemfile @@ -2,9 +2,29 @@ source 'https://rubygems.org' -# Specify your gem's dependencies in human_enum.gemspec gemspec +plugin 'bundler-multilock', '~> 1.3' +return unless Plugin.installed?('bundler-multilock') + +Plugin.send(:load_plugin, 'bundler-multilock') + +lockfile do + gem 'activerecord', '~> 7.1' # rubocop:disable Bundler/DuplicatedGem +end + +lockfile 'rails-6.1' do + gem 'activerecord', '~> 6.1.0' # rubocop:disable Bundler/DuplicatedGem +end + +lockfile 'rails-7.0' do + gem 'activerecord', '~> 7.0.0' # rubocop:disable Bundler/DuplicatedGem +end + +lockfile 'rails-7.1' do + gem 'activerecord', '~> 7.1.0' # rubocop:disable Bundler/DuplicatedGem +end + gem 'rake', '~> 13.0' gem 'sqlite3', '~> 1.4' diff --git a/Gemfile.lock b/Gemfile.lock index e5de414..7c2aff8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,37 @@ PATH remote: . specs: - human_enum (1.0.0) - activerecord (>= 6.1, < 7) + human_enum (1.1.0) + activerecord (>= 6.1, < 8) GEM remote: https://rubygems.org/ specs: - activemodel (6.1.7.7) - activesupport (= 6.1.7.7) - activerecord (6.1.7.7) - activemodel (= 6.1.7.7) - activesupport (= 6.1.7.7) - activesupport (6.1.7.7) + activemodel (7.1.3.3) + activesupport (= 7.1.3.3) + activerecord (7.1.3.3) + activemodel (= 7.1.3.3) + activesupport (= 7.1.3.3) + timeout (>= 0.4.0) + activesupport (7.1.3.3) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) minitest (>= 5.1) + mutex_m tzinfo (~> 2.0) - zeitwerk (~> 2.3) ast (2.4.2) base64 (0.1.1) + bigdecimal (3.1.8) coderay (1.1.3) concurrent-ruby (1.2.3) + connection_pool (2.4.1) diff-lcs (1.5.1) docile (1.4.0) + drb (2.2.1) ffi (1.16.3) formatador (1.1.0) guard (2.18.1) @@ -52,7 +60,8 @@ GEM rb-inotify (~> 0.9, >= 0.9.10) lumberjack (1.2.10) method_source (1.1.0) - minitest (5.22.3) + minitest (5.23.1) + mutex_m (0.2.0) nenv (0.3.0) notiffany (0.1.3) nenv (~> 0.1) @@ -61,19 +70,20 @@ GEM parser (3.3.1.0) ast (~> 2.4.1) racc - prism (0.27.0) + prism (0.29.0) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) - racc (1.7.3) + racc (1.8.0) rack (3.0.11) rainbow (3.1.1) rake (13.2.1) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) - regexp_parser (2.9.0) - rexml (3.2.6) + regexp_parser (2.9.2) + rexml (3.2.8) + strscan (>= 3.0.9) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) @@ -108,7 +118,7 @@ GEM rubocop-performance (1.21.0) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.24.1) + rubocop-rails (2.25.0) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) @@ -122,9 +132,9 @@ GEM rubocop-rspec_rails (~> 2.28) rubocop-rspec_rails (2.28.3) rubocop (~> 1.40) - ruby-lsp (0.16.6) + ruby-lsp (0.16.7) language_server-protocol (~> 3.17.0) - prism (>= 0.23.0, < 0.28) + prism (>= 0.29.0, < 0.30) sorbet-runtime (>= 0.5.10782) ruby-lsp-rails (0.3.6) ruby-lsp (>= 0.16.5, < 0.17.0) @@ -139,20 +149,30 @@ GEM simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - sorbet-runtime (0.5.11371) + sorbet-runtime (0.5.11391) + sqlite3 (1.7.3-aarch64-linux) + sqlite3 (1.7.3-arm-linux) + sqlite3 (1.7.3-arm64-darwin) + sqlite3 (1.7.3-x86-linux) sqlite3 (1.7.3-x86_64-darwin) sqlite3 (1.7.3-x86_64-linux) + strscan (3.1.0) thor (1.3.1) + timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) - zeitwerk (2.6.13) PLATFORMS - x86_64-darwin-22 + aarch64-linux + arm-linux + arm64-darwin + x86-linux + x86_64-darwin x86_64-linux DEPENDENCIES + activerecord (~> 7.1) guard (~> 2.18) guard-rspec (~> 4.7) guard-rubocop (~> 1.5) @@ -170,4 +190,4 @@ DEPENDENCIES sqlite3 (~> 1.4) BUNDLED WITH - 2.4.19 + 2.5.10 diff --git a/Gemfile.rails-6.1.lock b/Gemfile.rails-6.1.lock new file mode 100644 index 0000000..fa13ca9 --- /dev/null +++ b/Gemfile.rails-6.1.lock @@ -0,0 +1,184 @@ +PATH + remote: . + specs: + human_enum (1.1.0) + activerecord (>= 6.1, < 8) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (6.1.7.7) + activesupport (= 6.1.7.7) + activerecord (6.1.7.7) + activemodel (= 6.1.7.7) + activesupport (= 6.1.7.7) + activesupport (6.1.7.7) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + ast (2.4.2) + base64 (0.1.1) + coderay (1.1.3) + concurrent-ruby (1.2.3) + diff-lcs (1.5.1) + docile (1.4.0) + ffi (1.16.3) + formatador (1.1.0) + guard (2.18.1) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.13.0) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + guard-rubocop (1.5.0) + guard (~> 2.0) + rubocop (< 2.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + json (2.7.2) + language_server-protocol (3.17.0.3) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + lumberjack (1.2.10) + method_source (1.1.0) + minitest (5.23.1) + nenv (0.3.0) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) + parallel (1.24.0) + parser (3.3.1.0) + ast (~> 2.4.1) + racc + prism (0.29.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + racc (1.8.0) + rack (3.0.11) + rainbow (3.1.1) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + regexp_parser (2.9.2) + rexml (3.2.8) + strscan (>= 3.0.9) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubocop (1.56.4) + base64 (~> 0.1.1) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.3) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.31.3) + parser (>= 3.3.1.0) + rubocop-capybara (2.20.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.25.1) + rubocop (~> 1.41) + rubocop-performance (1.21.0) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rails (2.25.0) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + rubocop-rspec (2.29.2) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + rubocop-rspec_rails (~> 2.28) + rubocop-rspec_rails (2.28.3) + rubocop (~> 1.40) + ruby-lsp (0.16.7) + language_server-protocol (~> 3.17.0) + prism (>= 0.29.0, < 0.30) + sorbet-runtime (>= 0.5.10782) + ruby-lsp-rails (0.3.6) + ruby-lsp (>= 0.16.5, < 0.17.0) + sorbet-runtime (>= 0.5.9897) + ruby-lsp-rspec (0.1.11) + ruby-lsp (~> 0.16.0) + ruby-progressbar (1.13.0) + shellany (0.0.1) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) + sorbet-runtime (0.5.11391) + sqlite3 (1.7.3-aarch64-linux) + sqlite3 (1.7.3-arm-linux) + sqlite3 (1.7.3-arm64-darwin) + sqlite3 (1.7.3-x86-linux) + sqlite3 (1.7.3-x86_64-darwin) + sqlite3 (1.7.3-x86_64-linux) + strscan (3.1.0) + thor (1.3.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + zeitwerk (2.6.14) + +PLATFORMS + aarch64-linux + arm-linux + arm64-darwin + x86-linux + x86_64-darwin + x86_64-linux + +DEPENDENCIES + activerecord (~> 6.1.0) + guard (~> 2.18) + guard-rspec (~> 4.7) + guard-rubocop (~> 1.5) + human_enum! + rake (~> 13.0) + rspec (~> 3.12) + rubocop (~> 1.56.3) + rubocop-performance + rubocop-rails + rubocop-rake + rubocop-rspec + ruby-lsp-rails + ruby-lsp-rspec + simplecov (~> 0.22.0) + sqlite3 (~> 1.4) + +BUNDLED WITH + 2.5.10 diff --git a/Gemfile.rails-7.0.lock b/Gemfile.rails-7.0.lock new file mode 100644 index 0000000..53f1770 --- /dev/null +++ b/Gemfile.rails-7.0.lock @@ -0,0 +1,182 @@ +PATH + remote: . + specs: + human_enum (1.1.0) + activerecord (>= 6.1, < 8) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (7.0.8.3) + activesupport (= 7.0.8.3) + activerecord (7.0.8.3) + activemodel (= 7.0.8.3) + activesupport (= 7.0.8.3) + activesupport (7.0.8.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + ast (2.4.2) + base64 (0.1.1) + coderay (1.1.3) + concurrent-ruby (1.2.3) + diff-lcs (1.5.1) + docile (1.4.0) + ffi (1.16.3) + formatador (1.1.0) + guard (2.18.1) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.13.0) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + guard-rubocop (1.5.0) + guard (~> 2.0) + rubocop (< 2.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + json (2.7.2) + language_server-protocol (3.17.0.3) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + lumberjack (1.2.10) + method_source (1.1.0) + minitest (5.23.1) + nenv (0.3.0) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) + parallel (1.24.0) + parser (3.3.1.0) + ast (~> 2.4.1) + racc + prism (0.29.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + racc (1.8.0) + rack (3.0.11) + rainbow (3.1.1) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + regexp_parser (2.9.2) + rexml (3.2.8) + strscan (>= 3.0.9) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubocop (1.56.4) + base64 (~> 0.1.1) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.3) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.31.3) + parser (>= 3.3.1.0) + rubocop-capybara (2.20.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.25.1) + rubocop (~> 1.41) + rubocop-performance (1.21.0) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rails (2.25.0) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + rubocop-rspec (2.29.2) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + rubocop-rspec_rails (~> 2.28) + rubocop-rspec_rails (2.28.3) + rubocop (~> 1.40) + ruby-lsp (0.16.7) + language_server-protocol (~> 3.17.0) + prism (>= 0.29.0, < 0.30) + sorbet-runtime (>= 0.5.10782) + ruby-lsp-rails (0.3.6) + ruby-lsp (>= 0.16.5, < 0.17.0) + sorbet-runtime (>= 0.5.9897) + ruby-lsp-rspec (0.1.11) + ruby-lsp (~> 0.16.0) + ruby-progressbar (1.13.0) + shellany (0.0.1) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) + sorbet-runtime (0.5.11391) + sqlite3 (1.7.3-aarch64-linux) + sqlite3 (1.7.3-arm-linux) + sqlite3 (1.7.3-arm64-darwin) + sqlite3 (1.7.3-x86-linux) + sqlite3 (1.7.3-x86_64-darwin) + sqlite3 (1.7.3-x86_64-linux) + strscan (3.1.0) + thor (1.3.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + +PLATFORMS + aarch64-linux + arm-linux + arm64-darwin + x86-linux + x86_64-darwin + x86_64-linux + +DEPENDENCIES + activerecord (~> 7.0.0) + guard (~> 2.18) + guard-rspec (~> 4.7) + guard-rubocop (~> 1.5) + human_enum! + rake (~> 13.0) + rspec (~> 3.12) + rubocop (~> 1.56.3) + rubocop-performance + rubocop-rails + rubocop-rake + rubocop-rspec + ruby-lsp-rails + ruby-lsp-rspec + simplecov (~> 0.22.0) + sqlite3 (~> 1.4) + +BUNDLED WITH + 2.5.10 diff --git a/Gemfile.rails-7.1.lock b/Gemfile.rails-7.1.lock new file mode 100644 index 0000000..da6439e --- /dev/null +++ b/Gemfile.rails-7.1.lock @@ -0,0 +1,193 @@ +PATH + remote: . + specs: + human_enum (1.1.0) + activerecord (>= 6.1, < 8) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (7.1.3.3) + activesupport (= 7.1.3.3) + activerecord (7.1.3.3) + activemodel (= 7.1.3.3) + activesupport (= 7.1.3.3) + timeout (>= 0.4.0) + activesupport (7.1.3.3) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + ast (2.4.2) + base64 (0.1.1) + bigdecimal (3.1.8) + coderay (1.1.3) + concurrent-ruby (1.2.3) + connection_pool (2.4.1) + diff-lcs (1.5.1) + docile (1.4.0) + drb (2.2.1) + ffi (1.16.3) + formatador (1.1.0) + guard (2.18.1) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.13.0) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + guard-rubocop (1.5.0) + guard (~> 2.0) + rubocop (< 2.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + json (2.7.2) + language_server-protocol (3.17.0.3) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + lumberjack (1.2.10) + method_source (1.1.0) + minitest (5.23.1) + mutex_m (0.2.0) + nenv (0.3.0) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) + parallel (1.24.0) + parser (3.3.1.0) + ast (~> 2.4.1) + racc + prism (0.29.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + racc (1.8.0) + rack (3.0.11) + rainbow (3.1.1) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + regexp_parser (2.9.2) + rexml (3.2.8) + strscan (>= 3.0.9) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubocop (1.56.4) + base64 (~> 0.1.1) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.3) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.31.3) + parser (>= 3.3.1.0) + rubocop-capybara (2.20.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.25.1) + rubocop (~> 1.41) + rubocop-performance (1.21.0) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rails (2.25.0) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + rubocop-rspec (2.29.2) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + rubocop-rspec_rails (~> 2.28) + rubocop-rspec_rails (2.28.3) + rubocop (~> 1.40) + ruby-lsp (0.16.7) + language_server-protocol (~> 3.17.0) + prism (>= 0.29.0, < 0.30) + sorbet-runtime (>= 0.5.10782) + ruby-lsp-rails (0.3.6) + ruby-lsp (>= 0.16.5, < 0.17.0) + sorbet-runtime (>= 0.5.9897) + ruby-lsp-rspec (0.1.11) + ruby-lsp (~> 0.16.0) + ruby-progressbar (1.13.0) + shellany (0.0.1) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) + sorbet-runtime (0.5.11391) + sqlite3 (1.7.3-aarch64-linux) + sqlite3 (1.7.3-arm-linux) + sqlite3 (1.7.3-arm64-darwin) + sqlite3 (1.7.3-x86-linux) + sqlite3 (1.7.3-x86_64-darwin) + sqlite3 (1.7.3-x86_64-linux) + strscan (3.1.0) + thor (1.3.1) + timeout (0.4.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + +PLATFORMS + aarch64-linux + arm-linux + arm64-darwin + x86-linux + x86_64-darwin + x86_64-linux + +DEPENDENCIES + activerecord (~> 7.1.0) + guard (~> 2.18) + guard-rspec (~> 4.7) + guard-rubocop (~> 1.5) + human_enum! + rake (~> 13.0) + rspec (~> 3.12) + rubocop (~> 1.56.3) + rubocop-performance + rubocop-rails + rubocop-rake + rubocop-rspec + ruby-lsp-rails + ruby-lsp-rspec + simplecov (~> 0.22.0) + sqlite3 (~> 1.4) + +BUNDLED WITH + 2.5.10 diff --git a/Guardfile b/Guardfile index 2ca5fac..0bf5870 100644 --- a/Guardfile +++ b/Guardfile @@ -1,9 +1,9 @@ # frozen_string_literal: true -guard :rubocop, all_on_start: false, cli: '-a' do - watch(/.+\.rb$/) - watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) } -end +# guard :rubocop, all_on_start: false, cli: '-a' do +# watch(/.+\.rb$/) +# watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) } +# end guard :rspec, cmd: 'bundle exec rspec' do require 'guard/rspec/dsl' diff --git a/README.md b/README.md index 0f68b65..ea56fd4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This gem allows you to specify enum value translations in your I18n locale files like any other ActiveRecord attribute and adds helper methods to get humanized translations of enum values. -![Tests](https://github.com/rafasoares/human_enum/workflows/Tests/badge.svg) +[![Tests](https://github.com/rafasoares/human_enum/actions/workflows/tests.yml/badge.svg)](https://github.com/rafasoares/human_enum/actions/workflows/tests.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/b1caef25c888cde6688e/maintainability)](https://codeclimate.com/github/rafasoares/human_enum/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/b1caef25c888cde6688e/test_coverage)](https://codeclimate.com/github/rafasoares/human_enum/test_coverage) @@ -58,6 +58,10 @@ Then declare your enums as you normally would: ```ruby class MyModel < ApplicationRecord + # For Rails 7+ + enum :model_type, %i[default special] + + # For Rails 6 enum model_type: %i[default special] end ``` diff --git a/human_enum.gemspec b/human_enum.gemspec index 67516e1..c546e39 100644 --- a/human_enum.gemspec +++ b/human_enum.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |spec| spec.authors = ['Rafael Soares'] spec.email = ['893971+rafasoares@users.noreply.github.com'] - # Should always be the lowest maint version of Ruby + # Should always be the lowest maintained version of Ruby spec.required_ruby_version = '>= 3.0.0' spec.summary = 'Adds simple and easy I18n support for Rails enums' @@ -32,5 +32,5 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] - spec.add_dependency 'activerecord', '>= 6.1', '< 7' + spec.add_dependency 'activerecord', '>= 6.1', '< 8' end diff --git a/lib/human_enum.rb b/lib/human_enum.rb index e36c1ea..66cc35f 100644 --- a/lib/human_enum.rb +++ b/lib/human_enum.rb @@ -4,6 +4,7 @@ require 'active_support' require 'active_support/concern' require 'active_support/core_ext/array' +require 'active_support/core_ext/module/deprecation' require 'active_model/naming' require 'active_model/translation' require 'active_record/type' @@ -19,25 +20,67 @@ class Error < StandardError; end extend ActiveSupport::Concern + class << self + def deprecator = @deprecator ||= ActiveSupport::Deprecation.new('2.0', 'HumanEnum') + end + included do - def human_enum_value(enum_name) - enum_value = send enum_name - self.class.human_enum_value(enum_name, enum_value) unless enum_value.nil? + # DEPRECATED: This method is deprecated and will be removed in future versions. + # + # Returns the human-readable value of the specified enum. + # + # @param enum_name [Symbol] The name of the enum. + # @return [String] The human-readable value of the enum. + # @deprecated Use `human_` instead. + # :nocov: + def human_enum_value(enum_name, enum_value) + _translate_enum(enum_name, enum_value) + end + # :nocov: + + deprecate(human_enum_value: 'use `human_` instead', deprecator: HumanEnum.deprecator) + + private + + def _translate_enum(enum_name, enum_value = send(enum_name)) + self.class.send(:_translate_enum, enum_name, enum_value) end end - class_methods do - def enum(definitions) - super definitions + class_methods do # rubocop:disable Metrics/BlockLength + def enum(...) + super(...).tap { humanize_enums } + end - definitions.keys.without(:_prefix, :_suffix).each do |name| - human_enum name + # DEPRECATED: This method is deprecated and will be removed in future versions. + # + # Translates the given enum value into a human-readable string. + # + # @param enum_name [Symbol] The name of the enum. + # @param enum_value [Symbol] The value of the enum. + # @return [String] The human-readable string representation of the enum value. + # @deprecated Use `human_` instead. + # :nocov: + def human_enum_value(enum_name, enum_value) + _translate_enum(enum_name, enum_value) + end + # :nocov: + + deprecate(human_enum_value: 'use `human_` instead', deprecator: HumanEnum.deprecator) + + # Goes through all enums defined in the model and creates the necessary methods, if they don't exist yet. + def humanize_enums + defined_enums.each do |enum_name, values| + _define_instance_method(enum_name) + _define_class_method(enum_name, values) end end - def human_enum_value(enum_name, enum_value) + private + + def _translate_enum(enum_name, enum_value) attributes_scope = "#{i18n_scope}.attributes" - enum_key = "#{enum_name.to_s.pluralize}.#{enum_value}" + enum_key = [enum_name.to_s.pluralize, enum_value].compact.join('.') defaults = lookup_ancestors.map do |klass| :"#{attributes_scope}.#{klass.model_name.i18n_key}.#{enum_key}" @@ -49,14 +92,20 @@ def human_enum_value(enum_name, enum_value) I18n.t defaults.shift, default: defaults end - def human_enum(enum_name) - send :define_method, "human_#{enum_name}" do - human_enum_value enum_name + def _define_instance_method(enum_name) + return if method_defined?(:"human_#{enum_name}") + + define_method(:"human_#{enum_name}") do + _translate_enum(enum_name, send(enum_name)) end + end + def _define_class_method(enum_name, values) collection_name = enum_name.to_s.pluralize + return if respond_to?(:"human_#{collection_name}") + self.class.send :define_method, "human_#{collection_name}" do - human_enum_value enum_name, nil + values.to_h { |key, _| [key.to_sym, _translate_enum(enum_name, key)] } end end end diff --git a/lib/human_enum/version.rb b/lib/human_enum/version.rb index ae68fd1..9ed7298 100644 --- a/lib/human_enum/version.rb +++ b/lib/human_enum/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module HumanEnum - VERSION = '1.0.0' + VERSION = '1.1.0' end diff --git a/spec/human_enum_spec.rb b/spec/human_enum_spec.rb index 226941b..4367033 100644 --- a/spec/human_enum_spec.rb +++ b/spec/human_enum_spec.rb @@ -2,55 +2,38 @@ require 'setup_helper' -class TestModel < ActiveRecord::Base - include HumanEnum - - enum my_enum: %i[value other_value] -end - RSpec.describe HumanEnum do it 'has a version number' do expect(HumanEnum::VERSION).not_to be_nil end - context 'when included' do - subject do - Class.new(ActiveRecord::Base) do - include HumanEnum + if ActiveRecord.gem_version < '7.2' + context 'with Rails < 7 syntax' do + context 'with an array of values' do + include_examples 'translations', :size, + small: 'Small', medium: 'Medium', large: 'Large' end - end - - it { is_expected.to respond_to :human_enum_value } - end - - describe 'Model class methods' do - subject(:values) { TestModel.human_my_enums } - - let(:expected_values) do - { - value: 'Custom value', - other_value: 'Other custom value' - } - end - it 'returns a Hash with the translated values' do - expect(values).to eq expected_values + context 'with a Hash of values' do + include_examples 'translations', :color, + red: 'Red', blue: 'Violets are blue' + end end end - describe 'Model instance method' do - subject { TestModel.new(params).human_my_enum } - - context 'with a blank value' do - let(:params) { {} } - - it { is_expected.to be_nil } - end - - context 'with enum value = :other_value' do - let(:params) { { my_enum: :other_value } } + if ActiveRecord.gem_version >= '7' + context 'with Rails >= 7 syntax' do + context 'with an array of values' do + include_examples 'translations', :shape, + square: 'Square', + circle: 'You spin me right round, baby', + triangle: 'Pointy boi' + end - it { is_expected.to eq 'Other custom value' } + context 'with a Hash of values' do + include_examples 'translations', :direction, + north: 'Up?', south: 'South', east: 'East', west: 'West' + end end end end diff --git a/spec/setup_helper.rb b/spec/setup_helper.rb index e80686f..dd4577c 100644 --- a/spec/setup_helper.rb +++ b/spec/setup_helper.rb @@ -9,4 +9,4 @@ require 'bundler/setup' require 'human_enum' -Dir[File.join(__dir__, 'support', '*.rb')].each { |f| require f } +Dir[File.join(__dir__, 'support', '**', '*.rb')].each { |f| require f } diff --git a/spec/support/db.rb b/spec/support/db.rb index 8f79366..e1b3aff 100644 --- a/spec/support/db.rb +++ b/spec/support/db.rb @@ -11,7 +11,10 @@ ActiveRecord::Schema.define do create_table 'test_models' do |t| - t.string 'my_enum' + t.integer 'size' + t.string 'color' + t.string 'shape' + t.string 'direction' end end end diff --git a/spec/support/locales/en.yml b/spec/support/locales/en.yml index cb7389c..b7941a5 100644 --- a/spec/support/locales/en.yml +++ b/spec/support/locales/en.yml @@ -1,7 +1,13 @@ en: + attributes: + directions: + north: "Up?" activerecord: attributes: test_model: - my_enums: - value: Custom value - other_value: Other custom value + shapes: + circle: "You spin me right round, baby" + triangle: "Pointy boi" + colors: + red: "Red" + blue: "Violets are blue" diff --git a/spec/support/shared/translation_examples.rb b/spec/support/shared/translation_examples.rb new file mode 100644 index 0000000..ac0ed9a --- /dev/null +++ b/spec/support/shared/translation_examples.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'translations' do |enum_name, values| + let(:plural_enum_name) { enum_name.to_s.pluralize } + describe 'Model class methods' do + subject(:translated_values) { TestModel.public_send(:"human_#{plural_enum_name}") } + + it { is_expected.to eq values } + end + + describe 'Model instance method' do + values.each do |value, translation| + context "when #{enum_name} is #{value}" do + subject { TestModel.new(enum_name => value).public_send(:"human_#{enum_name}") } + + it { is_expected.to eq translation } + end + end + end +end diff --git a/spec/support/test_model.rb b/spec/support/test_model.rb new file mode 100644 index 0000000..407259f --- /dev/null +++ b/spec/support/test_model.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'active_record' + +class TestModel < ActiveRecord::Base + include HumanEnum + + if ActiveRecord.gem_version < '7.2' + enum size: %i[small medium large], + color: { red: 'ff0000', blue: '0000ff' } + end + + if ActiveRecord.gem_version >= '7' + enum :shape, %i[square circle triangle] + enum :direction, { north: 'N', south: 'S', east: 'E', west: 'W' } + end +end