infinum_json_api_setup 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +45 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +50 -12
  7. data/Gemfile +1 -0
  8. data/Gemfile.lock +1 -0
  9. data/README.md +8 -0
  10. data/Rakefile +3 -0
  11. data/base.gemfile +14 -0
  12. data/infinum_json_api_setup.gemspec +11 -16
  13. data/lib/generators/infinum_json_api_setup/templates/config/locales/json_api.en.yml +1 -0
  14. data/lib/infinum_json_api_setup/json_api/content_negotiation.rb +2 -2
  15. data/lib/infinum_json_api_setup/json_api/locale_negotiation.rb +45 -0
  16. data/lib/infinum_json_api_setup/json_api/serializer_options.rb +1 -1
  17. data/lib/infinum_json_api_setup/rspec/helpers/response_helper.rb +4 -4
  18. data/lib/infinum_json_api_setup/rspec/matchers/have_empty_data.rb +1 -1
  19. data/lib/infinum_json_api_setup/rspec/matchers/have_error_pointer.rb +1 -1
  20. data/lib/infinum_json_api_setup/rspec/matchers/have_resource_count_of.rb +1 -1
  21. data/lib/infinum_json_api_setup/version.rb +1 -1
  22. data/lib/infinum_json_api_setup.rb +3 -0
  23. data/rails.7.1.gemfile +8 -0
  24. data/rails.7.1.gemfile.lock +361 -0
  25. data/rails.8.0.gemfile +7 -0
  26. data/rails.8.0.gemfile.lock +380 -0
  27. data/spec/dummy/app/controllers/api/v1/base_controller.rb +1 -0
  28. data/spec/dummy/app/controllers/api/v1/hello_controller.rb +11 -0
  29. data/spec/dummy/app/controllers/api/v1/locations_controller.rb +7 -13
  30. data/spec/dummy/app/models/location.rb +1 -1
  31. data/spec/dummy/config/database.yml +3 -0
  32. data/spec/dummy/config/environments/production.rb +1 -1
  33. data/spec/dummy/config/initializers/i18n.rb +3 -0
  34. data/spec/dummy/config/locales/de.yml +2 -0
  35. data/spec/dummy/config/locales/json_api.de.yml +22 -0
  36. data/spec/dummy/config/locales/json_api.en.yml +1 -0
  37. data/spec/dummy/config/routes.rb +1 -0
  38. data/spec/infinum_json_api_setup/rspec/helpers/response_helper_spec.rb +234 -0
  39. data/spec/infinum_json_api_setup/rspec/matchers/have_empty_data_spec.rb +3 -2
  40. data/spec/rails_helper.rb +2 -6
  41. data/spec/requests/api/v1/content_negotiation_spec.rb +10 -2
  42. data/spec/requests/api/v1/error_handling_spec.rb +37 -19
  43. data/spec/requests/api/v1/locale_negotiation_spec.rb +66 -0
  44. data/spec/requests/api/v1/responder_spec.rb +1 -1
  45. data/spec/requests/api/v1/serializer_options_spec.rb +1 -1
  46. metadata +46 -99
  47. data/Gemfile +0 -10
  48. data/Gemfile.lock +0 -268
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bd39fc553b558ee1c3e92ef43209cb47f37b9ed04172f1e36394182de121d88
4
- data.tar.gz: b287940a9526e8aab6ec9edac50d1188a60cb5c7ea1dcb32849b33faffc789c5
3
+ metadata.gz: fd0a0f31918bb2f7f2c2fd1c89c7ef8704292bba7590c980c54ac8daa809c321
4
+ data.tar.gz: afb709b1deeb7891a4f7a65a248ffaebcbd4f0ad874e48d1c7c21dae623d3cb1
5
5
  SHA512:
6
- metadata.gz: 3753867e1c76fffa6e084aed49f7f57f8ea5181dbe43acc8357195bf1d9f3ad223bf0eabb3986637b8be264b3ef12ac700d6a0bbc29910d212cfc9f519f80b98
7
- data.tar.gz: 909a9883dc4188acb28819c16ee46a7279d3f5e8bfdd837e91d3272bc914d49c249f89615d5c11326145dca6983db41de9656ef084bee634b7c1bcabe97c67d4
6
+ metadata.gz: d4c5c8b5f7564d095d43efa4a292263dc8c5cc65c4066f5ee3078b7b7afefcbb4879570ec6474ae6aa690a775afbd97f319ce6d6d3c55585314bbf455a0a5ce8
7
+ data.tar.gz: 60da19ebe9c6ebc6edf1fba046621cd966ecb5c4a0436fcc251ac5a18a946e6323a7f5359fc11632a434abfc886cf61eea7c256b364eccb2319a29eac0bfd0c8
@@ -0,0 +1,45 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+
6
+ jobs:
7
+ build:
8
+ runs-on: ubuntu-latest
9
+ services:
10
+ database:
11
+ image: postgres:14
12
+ env:
13
+ POSTGRES_HOST_AUTH_METHOD: trust
14
+ ports:
15
+ - 5432:5432
16
+ options: >-
17
+ --health-cmd pg_isready
18
+ --health-interval 10s
19
+ --health-timeout 5s
20
+ --health-retries 5
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ ruby: ['3.2.9', '3.3.9', '3.4.5']
25
+ gemfile: ['rails.7.1.gemfile', 'rails.8.0.gemfile']
26
+ env:
27
+ BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
28
+ steps:
29
+ - uses: actions/checkout@v2
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: "${{ matrix.ruby }}"
34
+ - name: Install dependencies
35
+ run: bundle install
36
+ - name: Setup database
37
+ env:
38
+ BUNDLE_GEMFILE: "../../${{ matrix.gemfile }}"
39
+ run: |
40
+ cd spec/dummy
41
+ bundle exec rake db:test:prepare
42
+ - name: Run rubocop
43
+ run: bundle exec rubocop
44
+ - name: Run specs
45
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -4,3 +4,5 @@
4
4
  /spec/dummy/tmp/
5
5
 
6
6
  coverage
7
+
8
+ /pkg
data/.rubocop.yml CHANGED
@@ -22,7 +22,7 @@ Style/FrozenStringLiteralComment:
22
22
  Enabled: false
23
23
 
24
24
  AllCops:
25
- TargetRubyVersion: 2.7
25
+ TargetRubyVersion: 3.2
26
26
  Exclude:
27
27
  - 'spec/dummy/db/schema.rb'
28
28
  - 'spec/dummy/db/migrate/*.rb'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.2
1
+ 3.4.5
data/CHANGELOG.md CHANGED
@@ -1,17 +1,55 @@
1
- ## 0.0.7 (Oct 25th, 2021)
2
- - fix runtime depenency loading
1
+ # Change Log for infinum/infinum-json-api-setup
3
2
 
4
- [Compare v0.0.6...v0.0.7](https://github.com/infinum/infinum-json-api-setup/compare/v0.0.6...v0.0.7)
3
+ All notable changes to this project will be documented in this file.
5
4
 
6
- ## 0.0.6 (Oct 25th, 2021)
7
- - update installation instructions in README
8
- - promote jsonapi-query-builder and jsonapi-serializer to runtime dependencies
9
- - start CHANGELOG
5
+ This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a CHANGELOG](https://keepachangelog.com/).
10
6
 
11
- [Compare v0.0.5...v0.0.6](https://github.com/infinum/infinum-json-api-setup/compare/v0.0.5...v0.0.6)
7
+ ## [Unreleased]
12
8
 
13
- ## 0.0.5 (Oct 6th, 2021)
14
- - bump jsonapi-query_builder dependency
15
- - bump Nokogiri dependency (due to CVE)
9
+ ### Changes
16
10
 
17
- [Compare v0.0.4...v0.0.4](https://github.com/infinum/infinum-json-api-setup/compare/v0.0.4...v0.0.5)
11
+ ## [0.1.0] - 2025-11-03
12
+
13
+ ### Added
14
+ - Rails 8 support
15
+ - Locale negotiation
16
+
17
+ ### Changes
18
+ - Reformat CHANGELOG according to infinum/open-source-project-template
19
+ - Drop support for Rails 6.1
20
+ - Relax json_schemer dependency
21
+
22
+ ### Fixed
23
+ - Ruby 3.4 ostruct deprecation warning
24
+
25
+ ## [0.0.8] - 2021-10-25
26
+
27
+ ### Updated
28
+ - Bump pagy dependency
29
+
30
+ ## [0.0.7] - 2021-10-25
31
+
32
+ ### Fixed
33
+ - Runtime depenency loading
34
+
35
+ ## [0.0.6] - 2021-10-25
36
+
37
+ ### Added
38
+ - CHANGELOG
39
+
40
+ ### Changed
41
+ - Update installation instructions in README
42
+ - Promote jsonapi-query-builder and jsonapi-serializer to runtime dependencies
43
+
44
+ ## [0.0.5] - 2021-10-06
45
+
46
+ ### Updated
47
+ - Bump jsonapi-query_builder dependency
48
+ - Bump Nokogiri dependency (due to CVE)
49
+
50
+ [Unreleased]: https://github.com/infinum/infinum-json-api-setup/compare/v0.1.0...HEAD
51
+ [0.1.0]: https://github.com/infinum/infinum-json-api-setup/compare/v0.0.8...v0.1.0
52
+ [0.0.8]: https://github.com/infinum/infinum-json-api-setup/compare/v0.0.7...v0.0.8
53
+ [0.0.7]: https://github.com/infinum/infinum-json-api-setup/compare/v0.0.6...v0.0.7
54
+ [0.0.6]: https://github.com/infinum/infinum-json-api-setup/compare/v0.0.5...v0.0.6
55
+ [0.0.5]: https://github.com/infinum/infinum-json-api-setup/compare/v0.0.4...v0.0.5
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ rails.7.1.gemfile
data/Gemfile.lock ADDED
@@ -0,0 +1 @@
1
+ rails.7.1.gemfile.lock
data/README.md CHANGED
@@ -24,6 +24,7 @@ module Api
24
24
  class BaseController < ActionController::API
25
25
  include InfinumJsonApiSetup::JsonApi::ErrorHandling
26
26
  include InfinumJsonApiSetup::JsonApi::ContentNegotiation
27
+ include InfinumJsonApiSetup::JsonApi::LocaleNegotiation
27
28
 
28
29
  self.responder = InfinumJsonApiSetup::JsonApi::Responder
29
30
  respond_to :json_api
@@ -71,6 +72,13 @@ This section explains the under-the-hood behavior of the library.
71
72
  ### Content negotiation
72
73
  `InfinumJsonApiSetup::JsonApi::ContentNegotiation` module is designed to integrate [server responsibilities](https://jsonapi.org/format/#content-negotiation-servers) of content negotiation protocol described by the JSON:API specification.
73
74
 
75
+ ### Locale negotiation
76
+ `InfinumJsonApiSetup::JsonApi::LocaleNegotiation` module ensures that request handling happens within the locale best matching the `Accept-Language` header.
77
+
78
+ - **Default behavior:** locale falls back to the application's default when the header is missing.
79
+ - **Invalid locales:** enable graceful fallback by setting `self.fallback_to_default_locale_if_invalid = true` in your controller when you want to disregard unrecognized locales instead of raising `json_api.errors.bad_request.invalid_locale`.
80
+ - **Error handling:** when fallback is disabled (default), requests with invalid locales trigger a JSON:API formatted bad request response.
81
+
74
82
  ### Error handling
75
83
  `InfinumJsonApiSetup::JsonApi::ErrorHandling` module is designed to catch and handle common exceptions that might bubble up when processing a request.
76
84
 
data/Rakefile CHANGED
@@ -1 +1,4 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'gemika/tasks'
3
+
4
+ task default: 'matrix:spec'
data/base.gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'bundler-audit', require: false
4
+ gem 'factory_bot', '~> 6.2'
5
+ gem 'faker', '~> 2.18'
6
+ gem 'overcommit', '~> 0.58', require: false
7
+ gem 'pg'
8
+ gem 'pry-rails'
9
+ gem 'pundit'
10
+ gem 'rake', require: false
11
+ gem 'rubocop', '~> 1.0', require: false
12
+ gem 'rubocop-infinum', require: false
13
+ gem 'rubocop-rake', require: false
14
+ gem 'simplecov', require: false
@@ -10,21 +10,16 @@ Gem::Specification.new do |s|
10
10
  s.files = `git ls-files`.split("\n")
11
11
  s.homepage = 'https://github.com/infinum/infinum-json-api-setup'
12
12
  s.license = 'MIT'
13
- s.required_ruby_version = '> 2.7'
13
+ s.required_ruby_version = '>= 3.2'
14
+ s.metadata = { 'rubygems_mfa_required' => 'true' }
14
15
 
15
- s.add_runtime_dependency 'jsonapi_parameters'
16
- s.add_runtime_dependency 'jsonapi-query_builder'
17
- s.add_runtime_dependency 'jsonapi-serializer'
18
- s.add_runtime_dependency 'json_schemer', '~> 0.2'
19
- s.add_runtime_dependency 'pagy'
20
- s.add_runtime_dependency 'rails'
21
- s.add_runtime_dependency 'responders'
22
-
23
- s.add_development_dependency 'overcommit', '~> 0.58'
24
- s.add_development_dependency 'pg'
25
- s.add_development_dependency 'pry-rails'
26
- s.add_development_dependency 'pundit'
27
- s.add_development_dependency 'rake'
28
- s.add_development_dependency 'rspec-rails', '~> 5.0'
29
- s.add_development_dependency 'simplecov'
16
+ s.add_dependency 'accept_language', '~> 2.0'
17
+ s.add_dependency 'jsonapi_parameters'
18
+ s.add_dependency 'jsonapi-query_builder'
19
+ s.add_dependency 'jsonapi-serializer'
20
+ s.add_dependency 'json_schemer', '>= 0.2', '< 3'
21
+ s.add_dependency 'ostruct'
22
+ s.add_dependency 'pagy', '~> 8.0'
23
+ s.add_dependency 'rails'
24
+ s.add_dependency 'responders'
30
25
  end
@@ -4,6 +4,7 @@ en:
4
4
  bad_request:
5
5
  title: Bad Request
6
6
  detail: Bad request
7
+ invalid_locale: Invalid locale
7
8
  not_found:
8
9
  title: Not found
9
10
  detail: Resource not found
@@ -16,9 +16,9 @@ module InfinumJsonApiSetup
16
16
  end
17
17
 
18
18
  def valid_content_type?
19
- return true if request.body.size.zero?
19
+ return true if request.body.nil? || request.body.size.zero? # rubocop:disable Style/ZeroLengthPredicate
20
20
 
21
- request.content_type == Mime.fetch(:json_api)
21
+ request.content_mime_type == Mime.fetch(:json_api)
22
22
  end
23
23
 
24
24
  def acceptable?
@@ -0,0 +1,45 @@
1
+ module InfinumJsonApiSetup
2
+ module JsonApi
3
+ module LocaleNegotiation
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ around_action :setup_locale
8
+ class_attribute :fallback_to_default_locale_if_invalid, default: false
9
+ end
10
+
11
+ def rescue_with_handler(*)
12
+ I18n.with_locale(locale) { super }
13
+ end
14
+
15
+ private
16
+
17
+ def setup_locale(&)
18
+ return render_invalid_locale_error if locale.blank?
19
+
20
+ I18n.with_locale(locale, &)
21
+ end
22
+
23
+ def locale
24
+ return I18n.default_locale if locale_from_request.blank?
25
+
26
+ parsed_locale = AcceptLanguage.parse(locale_from_request).match(*I18n.available_locales)
27
+
28
+ if parsed_locale.present?
29
+ parsed_locale
30
+ elsif fallback_to_default_locale_if_invalid
31
+ I18n.default_locale
32
+ end
33
+ end
34
+
35
+ def locale_from_request
36
+ request.env['HTTP_ACCEPT_LANGUAGE']
37
+ end
38
+
39
+ def render_invalid_locale_error
40
+ message = I18n.t('json_api.errors.bad_request.invalid_locale')
41
+ render_error(InfinumJsonApiSetup::Error::BadRequest.new(message:))
42
+ end
43
+ end
44
+ end
45
+ end
@@ -33,7 +33,7 @@ module InfinumJsonApiSetup
33
33
  total_count: pagination_details.count,
34
34
  padding: pagination_details.vars.fetch(:outset).to_i,
35
35
  page_size: pagination_details.vars.fetch(:items).to_i,
36
- max_page_size: Pagy::VARS[:max_items]
36
+ max_page_size: Pagy::DEFAULT[:max_items]
37
37
  }
38
38
  end
39
39
 
@@ -9,14 +9,14 @@ module InfinumJsonApiSetup
9
9
  def response_item
10
10
  raise 'json response is not an item' if json_response[:data].is_a?(Array)
11
11
 
12
- OpenStruct.new(json_response[:data][:attributes])
12
+ OpenStruct.new(json_response[:data][:attributes]) # rubocop:disable Style/OpenStructUse
13
13
  end
14
14
 
15
15
  def response_collection
16
16
  raise 'json response is not a collection' unless json_response[:data].is_a?(Array)
17
17
 
18
18
  json_response[:data].map do |item|
19
- OpenStruct.new(id: item[:id], type: item[:type], **item[:attributes])
19
+ OpenStruct.new(id: item[:id], type: item[:type], **item[:attributes]) # rubocop:disable Style/OpenStructUse
20
20
  end
21
21
  end
22
22
 
@@ -24,7 +24,7 @@ module InfinumJsonApiSetup
24
24
  case response_type
25
25
  when :item then json_response.dig(:data, :relationships)
26
26
  when :collection then json_response[:data].pluck(:relationships)
27
- else raise ArgumentError ':response_type must be one of [:item, :collection]'
27
+ else raise ArgumentError, ':response_type must be one of [:item, :collection]'
28
28
  end
29
29
  end
30
30
 
@@ -34,7 +34,7 @@ module InfinumJsonApiSetup
34
34
 
35
35
  def response_included
36
36
  json_response[:included].map do |item|
37
- OpenStruct.new(id: item[:id], type: item[:type], **item[:attributes])
37
+ OpenStruct.new(id: item[:id], type: item[:type], **item[:attributes]) # rubocop:disable Style/OpenStructUse
38
38
  end
39
39
  end
40
40
 
@@ -2,7 +2,7 @@ module InfinumJsonApiSetup
2
2
  module RSpec
3
3
  module Matchers
4
4
  # @return [InfinumJsonApiSetup::Rspec::Matchers::HaveEmptyData]
5
- def have_empty_data # rubocop:disable Naming/PredicateName
5
+ def have_empty_data # rubocop:disable Naming/PredicatePrefix
6
6
  HaveEmptyData.new
7
7
  end
8
8
 
@@ -3,7 +3,7 @@ module InfinumJsonApiSetup
3
3
  module Matchers
4
4
  # @param [String] pointer
5
5
  # @return [InfinumJsonApiSetup::Rspec::Matchers::HaveErrorPointer]
6
- def have_error_pointer(pointer) # rubocop:disable Naming/PredicateName
6
+ def have_error_pointer(pointer) # rubocop:disable Naming/PredicatePrefix
7
7
  HaveErrorPointer.new(pointer)
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ module InfinumJsonApiSetup
3
3
  module Matchers
4
4
  # @param [Integer] expected_count
5
5
  # @return [InfinumJsonApiSetup::Rspec::Matchers::HaveResourceCountOf]
6
- def have_resource_count_of(expected_count) # rubocop:disable Naming/PredicateName
6
+ def have_resource_count_of(expected_count) # rubocop:disable Naming/PredicatePrefix
7
7
  HaveResourceCountOf.new(expected_count)
8
8
  end
9
9
 
@@ -1,3 +1,3 @@
1
1
  module InfinumJsonApiSetup
2
- VERSION = '0.0.7'.freeze
2
+ VERSION = '0.1.0'.freeze
3
3
  end
@@ -1,9 +1,11 @@
1
1
  require 'rails'
2
2
 
3
+ require 'accept_language'
3
4
  require 'json'
4
5
  require 'jsonapi_parameters'
5
6
  require 'jsonapi/serializer'
6
7
  require 'json_schemer'
8
+ require 'ostruct'
7
9
  require 'responders'
8
10
 
9
11
  require 'pagy'
@@ -14,6 +16,7 @@ require 'infinum_json_api_setup/json_api/error_handling'
14
16
  require 'infinum_json_api_setup/json_api/error_serializer'
15
17
 
16
18
  require 'infinum_json_api_setup/json_api/content_negotiation'
19
+ require 'infinum_json_api_setup/json_api/locale_negotiation'
17
20
  require 'infinum_json_api_setup/json_api/request_parsing'
18
21
  require 'infinum_json_api_setup/json_api/serializer_options'
19
22
  require 'infinum_json_api_setup/json_api/responder'
data/rails.7.1.gemfile ADDED
@@ -0,0 +1,8 @@
1
+ eval(File.read(File.expand_path('base.gemfile', __dir__))) # rubocop:disable Security/Eval
2
+
3
+ gem 'gemika'
4
+ gem 'observer'
5
+ gem 'rails', '~> 7.1.0'
6
+ gem 'rspec-rails', '~> 7.0', require: false
7
+
8
+ gemspec