From 4a9e54db95d455f2c48cf4e2c8e630bf7ba53a2b Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Tue, 17 Jun 2025 16:32:27 +0100 Subject: [PATCH 01/70] Refactor database schema definitions for clarity and consistency --- test/fixtures/active_record.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/fixtures/active_record.rb b/test/fixtures/active_record.rb index 1209302fd..e6866785c 100644 --- a/test/fixtures/active_record.rb +++ b/test/fixtures/active_record.rb @@ -52,7 +52,7 @@ end create_table :posts, force: true do |t| - t.string :title, length: 255 + t.string :title, limit: 255 t.text :body t.integer :author_id t.integer :parent_post_id @@ -85,17 +85,20 @@ end create_table :posts_tags, force: true do |t| - t.references :post, :tag, index: true + t.references :post, index:true + t.references :tag, index:true end add_index :posts_tags, [:post_id, :tag_id], unique: true create_table :special_post_tags, force: true do |t| - t.references :post, :tag, index: true + t.references :post, index: true + t.references :tag, index: true end add_index :special_post_tags, [:post_id, :tag_id], unique: true create_table :comments_tags, force: true do |t| - t.references :comment, :tag, index: true + t.references :comment, index: true + t.references :tag, index: true end create_table :iso_currencies, id: false, force: true do |t| @@ -324,8 +327,8 @@ create_table :related_things, force: true do |t| t.string :name - t.references :from, references: :thing - t.references :to, references: :thing + t.references :from, foreign_key: { to_table: :things } + t.references :to, foreign_key: { to_table: :things } t.timestamps null: false end From dea548e82f4ff5cb7104a5757d1f07e10df0f9fc Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:09:04 +0100 Subject: [PATCH 02/70] Update Gemfile to simplify SQLite3 version handling --- Gemfile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index 2535d0200..f022a438b 100644 --- a/Gemfile +++ b/Gemfile @@ -10,12 +10,9 @@ version = ENV['RAILS_VERSION'] || 'default' platforms :ruby do gem 'pg' - - if version.start_with?('4.2', '5.0') - gem 'sqlite3', '~> 1.3.13' - else - gem 'sqlite3', '~> 1.4' - end + gem 'mysql2' + gem 'sqlite3' + gem 'csv' end case version @@ -26,4 +23,4 @@ when 'default' gem 'railties', '>= 6.0' else gem 'railties', "~> #{version}" -end \ No newline at end of file +end From ff8bc723a13eb68ce669479ff6d750a3241aa4c7 Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:09:32 +0100 Subject: [PATCH 03/70] Add missing require statement for Rails generators in controller and resource generators --- lib/generators/jsonapi/controller_generator.rb | 1 + lib/generators/jsonapi/resource_generator.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/generators/jsonapi/controller_generator.rb b/lib/generators/jsonapi/controller_generator.rb index 41ee4eb1e..d6aba8bf9 100644 --- a/lib/generators/jsonapi/controller_generator.rb +++ b/lib/generators/jsonapi/controller_generator.rb @@ -1,3 +1,4 @@ +require 'rails/generators' module Jsonapi class ControllerGenerator < Rails::Generators::NamedBase source_root File.expand_path('../templates', __FILE__) diff --git a/lib/generators/jsonapi/resource_generator.rb b/lib/generators/jsonapi/resource_generator.rb index 80aa24b4d..25feb14a1 100644 --- a/lib/generators/jsonapi/resource_generator.rb +++ b/lib/generators/jsonapi/resource_generator.rb @@ -1,3 +1,4 @@ +require 'rails/generators' module Jsonapi class ResourceGenerator < Rails::Generators::NamedBase source_root File.expand_path('../templates', __FILE__) From e83a16044f0308cbb3be1864e3f48ca2f04ec5c7 Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:13:58 +0100 Subject: [PATCH 04/70] Add JSONAPI::CompatibilityHelper module for version-safe deprecation warnings --- lib/jsonapi/compatibility_helper.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 lib/jsonapi/compatibility_helper.rb diff --git a/lib/jsonapi/compatibility_helper.rb b/lib/jsonapi/compatibility_helper.rb new file mode 100644 index 000000000..516609349 --- /dev/null +++ b/lib/jsonapi/compatibility_helper.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# JSONAPI::CompatibilityHelper +# +# This module provides a version-safe method for issuing deprecation warnings +# that works across multiple versions of Rails (7.x, 8.x, etc). +# +# Usage: +# JSONAPI::CompatibilityHelper.deprecation_warn("Your deprecation message") +# +# The method will use the public `warn` method if available, otherwise it will +# use `send(:warn, ...)` to maintain compatibility with Rails 8+ where `warn` +# is private. +# +# Example: +# JSONAPI::CompatibilityHelper.deprecation_warn("This feature is deprecated.") + +module JSONAPI + module CompatibilityHelper + def deprecation_warn(message) + if ActiveSupport::Deprecation.respond_to?(:warn) && ActiveSupport::Deprecation.public_method_defined?(:warn) + ActiveSupport::Deprecation.warn(message) + else + ActiveSupport::Deprecation.send(:warn, message) + end + end + module_function :deprecation_warn + end +end From 0eb11bc3ea54650778750a9e603e0ffecd99a6ea Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:14:45 +0100 Subject: [PATCH 05/70] Refactor deprecation warnings to use CompatibilityHelper and ensure consistent require statements --- lib/jsonapi/acts_as_resource_controller.rb | 10 +++++----- lib/jsonapi/basic_resource.rb | 9 +++++---- lib/jsonapi/configuration.rb | 10 +++++----- lib/jsonapi/relationship.rb | 4 ++-- lib/jsonapi/resource.rb | 2 +- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/jsonapi/acts_as_resource_controller.rb b/lib/jsonapi/acts_as_resource_controller.rb index e448fa0ea..8b29043d1 100644 --- a/lib/jsonapi/acts_as_resource_controller.rb +++ b/lib/jsonapi/acts_as_resource_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'csv' - +require_relative 'compatibility_helper' module JSONAPI module ActsAsResourceController MEDIA_TYPE_MATCHER = /.+".+"[^,]*|[^,]+/ @@ -63,16 +63,16 @@ def index_related_resources def get_related_resource # :nocov: - ActiveSupport::Deprecation.warn "In #{self.class.name} you exposed a `get_related_resource`"\ - " action. Please use `show_related_resource` instead." + JSONAPI::CompatibilityHelper.deprecation_warn("In #{self.class.name} you exposed a `get_related_resource`"\ + " action. Please use `show_related_resource` instead.") show_related_resource # :nocov: end def get_related_resources # :nocov: - ActiveSupport::Deprecation.warn "In #{self.class.name} you exposed a `get_related_resources`"\ - " action. Please use `index_related_resources` instead." + JSONAPI::CompatibilityHelper.deprecation_warn("In #{self.class.name} you exposed a `get_related_resources`"\ + " action. Please use `index_related_resources` instead.") index_related_resources # :nocov: end diff --git a/lib/jsonapi/basic_resource.rb b/lib/jsonapi/basic_resource.rb index 2eeba5c5d..d35ad796d 100644 --- a/lib/jsonapi/basic_resource.rb +++ b/lib/jsonapi/basic_resource.rb @@ -2,7 +2,7 @@ require 'jsonapi/callbacks' require 'jsonapi/configuration' - +require_relative 'compatibility_helper' module JSONAPI class BasicResource include Callbacks @@ -547,7 +547,7 @@ def attribute(attribute_name, options = {}) check_reserved_attribute_name(attr) if (attr == :id) && (options[:format].nil?) - ActiveSupport::Deprecation.warn('Id without format is no longer supported. Please remove ids from attributes, or specify a format.') + JSONAPI::CompatibilityHelper.deprecation_warn('Id without format is deprecated. Please specify a format for the id attribute.') end check_duplicate_attribute_name(attr) if options[:format].nil? @@ -609,11 +609,12 @@ def has_one(*attrs) end def belongs_to(*attrs) - ActiveSupport::Deprecation.warn "In #{name} you exposed a `has_one` relationship "\ + + JSONAPI::CompatibilityHelper.deprecation_warn( "In #{name} you exposed a `has_one` relationship "\ " using the `belongs_to` class method. We think `has_one`" \ " is more appropriate. If you know what you're doing," \ " and don't want to see this warning again, override the" \ - " `belongs_to` class method on your resource." + " `belongs_to` class method on your resource.") _add_relationship(Relationship::ToOne, *attrs) end diff --git a/lib/jsonapi/configuration.rb b/lib/jsonapi/configuration.rb index 6cd5d8e1b..e1a7e1c61 100644 --- a/lib/jsonapi/configuration.rb +++ b/lib/jsonapi/configuration.rb @@ -3,7 +3,7 @@ require 'jsonapi/formatter' require 'jsonapi/processor' require 'concurrent' - +require_relative 'compatibility_helper' module JSONAPI class Configuration attr_reader :json_key_format, @@ -227,7 +227,7 @@ def exception_class_allowed?(e) end def default_processor_klass=(default_processor_klass) - ActiveSupport::Deprecation.warn('`default_processor_klass` has been replaced by `default_processor_klass_name`.') + JSONAPI::CompatibilityHelper.deprecation_warn('`default_processor_klass` has been replaced by `default_processor_klass_name`.') @default_processor_klass = default_processor_klass end @@ -241,18 +241,18 @@ def default_processor_klass_name=(default_processor_klass_name) end def allow_include=(allow_include) - ActiveSupport::Deprecation.warn('`allow_include` has been replaced by `default_allow_include_to_one` and `default_allow_include_to_many` options.') + JSONAPI::CompatibilityHelper.deprecation_warn('`allow_include` has been replaced by `default_allow_include_to_one` and `default_allow_include_to_many` options.') @default_allow_include_to_one = allow_include @default_allow_include_to_many = allow_include end def whitelist_all_exceptions=(allow_all_exceptions) - ActiveSupport::Deprecation.warn('`whitelist_all_exceptions` has been replaced by `allow_all_exceptions`') + JSONAPI::CompatibilityHelper.deprecation_warn('`whitelist_all_exceptions` has been replaced by `allow_all_exceptions`') @allow_all_exceptions = allow_all_exceptions end def exception_class_whitelist=(exception_class_allowlist) - ActiveSupport::Deprecation.warn('`exception_class_whitelist` has been replaced by `exception_class_allowlist`') + JSONAPI::CompatibilityHelper.deprecation_warn('`exception_class_whitelist` has been replaced by `exception_class_allowlist`') @exception_class_allowlist = exception_class_allowlist end diff --git a/lib/jsonapi/relationship.rb b/lib/jsonapi/relationship.rb index 8824fc65d..62c17d9c8 100644 --- a/lib/jsonapi/relationship.rb +++ b/lib/jsonapi/relationship.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true - +require_relative 'compatibility_helper' module JSONAPI class Relationship attr_reader :acts_as_set, :foreign_key, :options, :name, @@ -21,7 +21,7 @@ def initialize(name, options = {}) @polymorphic = options.fetch(:polymorphic, false) == true @polymorphic_types = options[:polymorphic_types] if options[:polymorphic_relations] - ActiveSupport::Deprecation.warn('Use polymorphic_types instead of polymorphic_relations') + JSONAPI::CompatibilityHelper.deprecation_warn('Use polymorphic_types instead of polymorphic_relations') @polymorphic_types ||= options[:polymorphic_relations] end diff --git a/lib/jsonapi/resource.rb b/lib/jsonapi/resource.rb index 4d34dd290..421b46ea2 100644 --- a/lib/jsonapi/resource.rb +++ b/lib/jsonapi/resource.rb @@ -4,4 +4,4 @@ module JSONAPI class Resource < ActiveRelationResource root_resource end -end \ No newline at end of file +end From 652fdb5858b4a099b772700ecfbb09a758ec3e34 Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:15:04 +0100 Subject: [PATCH 06/70] Add nil check for relation_position to prevent processing errors --- lib/jsonapi/active_relation_resource.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/jsonapi/active_relation_resource.rb b/lib/jsonapi/active_relation_resource.rb index 581ed1e02..bfe88af26 100644 --- a/lib/jsonapi/active_relation_resource.rb +++ b/lib/jsonapi/active_relation_resource.rb @@ -666,10 +666,14 @@ def find_related_polymorphic_fragments(source_fragments, relationship, options, end relation_position = relation_positions[row[2].downcase.pluralize] - model_fields = relation_position[:model_fields] - cache_field = relation_position[:cache_field] - cache_offset = relation_position[:cache_offset] - field_offset = relation_position[:field_offset] + if relation_position + model_fields = relation_position[:model_fields] + cache_field = relation_position[:cache_field] + cache_offset = relation_position[:cache_offset] + field_offset = relation_position[:field_offset] + else + next # Skip processing if relation_position is nil + end if cache_field related_fragments[rid].cache = cast_to_attribute_type(row[cache_offset], cache_field[:type]) From 45328e382f616e33d02777d3221cfa0cd0acd121 Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:15:19 +0100 Subject: [PATCH 07/70] Update test_helper.rb to improve deprecation handling and unify fixture paths --- test/test_helper.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 9850a49c6..f6f9c1b70 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -23,7 +23,6 @@ ENV['DATABASE_URL'] ||= "sqlite3:test_db" require 'active_record/railtie' -require 'rails/test_help' require 'minitest/mock' require 'jsonapi-resources' require 'pry' @@ -42,7 +41,11 @@ config.json_key_format = :camelized_key end -ActiveSupport::Deprecation.silenced = true +if ActiveSupport::Deprecation.respond_to?(:behavior=) + ActiveSupport::Deprecation.behavior = :silence +elsif ActiveSupport::Deprecation.respond_to?(:silenced=) + ActiveSupport::Deprecation.silenced = true +end puts "Testing With RAILS VERSION #{Rails.version}" @@ -457,12 +460,12 @@ def run_in_transaction? true end - self.fixture_path = "#{Rails.root}/fixtures" + self.fixture_paths = ["#{Rails.root}/fixtures"] fixtures :all end class ActiveSupport::TestCase - self.fixture_path = "#{Rails.root}/fixtures" + self.fixture_paths = ["#{Rails.root}/fixtures"] fixtures :all setup do @routes = TestApp.routes @@ -470,7 +473,7 @@ class ActiveSupport::TestCase end class ActionDispatch::IntegrationTest - self.fixture_path = "#{Rails.root}/fixtures" + self.fixture_paths = ["#{Rails.root}/fixtures"] fixtures :all def assert_jsonapi_response(expected_status, msg = nil) From 35aef58d435583dd0b474814dffd469e93405668 Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:48:44 +0100 Subject: [PATCH 08/70] Refactor CI configuration to simplify Ruby and Rails versions --- .github/workflows/ruby.yml | 57 +++++--------------------------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index aeb9b1ae9..0fe41e0c2 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -2,67 +2,25 @@ name: CI on: push: - branches: [ 'master', 'release-0-8', 'release-0-9', 'release-0-10' ] + branches: [ 'master' ] pull_request: branches: ['**'] jobs: tests: runs-on: ubuntu-latest - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: password - POSTGRES_DB: test - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 strategy: fail-fast: false matrix: ruby: - - 2.6 - - 2.7 - - '3.0' - - 3.1 - - 3.2 + - '3.3' + - '3.2' rails: - - 7.0.4 - - 6.1.7 - - 6.0.6 - - 5.2.8.1 - - 5.1.7 + - '7.1' + - '7.0' + - '8.0.2' database_url: - - postgresql://postgres:password@localhost:5432/test - sqlite3:test_db - exclude: - - ruby: 3.2 - rails: 6.0.6 - - ruby: 3.2 - rails: 5.2.8.1 - - ruby: 3.2 - rails: 5.1.7 - - ruby: 3.1 - rails: 6.0.6 - - ruby: 3.1 - rails: 5.2.8.1 - - ruby: 3.1 - rails: 5.1.7 - - ruby: '3.0' - rails: 6.0.6 - - ruby: '3.0' - rails: 5.2.8.1 - - ruby: '3.0' - rails: 5.1.7 - - ruby: 2.6 - rails: 7.0.4 - - database_url: postgresql://postgres:password@localhost:5432/test - rails: 5.1.7 env: RAILS_VERSION: ${{ matrix.rails }} DATABASE_URL: ${{ matrix.database_url }} @@ -73,7 +31,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - - name: Install dependencies - run: bundle install --jobs 4 --retry 3 + bundler-cache: true - name: Run tests run: bundle exec rake test From a7f21c4d6f3a9b675a63abdb97b10cc4bd773ae2 Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 11:02:50 +0100 Subject: [PATCH 09/70] Update gemspec and version to reflect Sanger Institute ownership and version change to 0.2.0 --- jsonapi-resources.gemspec | 10 +++++----- lib/jsonapi/resources/version.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index eb3c67fa5..22745c81d 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -4,13 +4,13 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'jsonapi/resources/version' Gem::Specification.new do |spec| - spec.name = 'jsonapi-resources' + spec.name = 'sanger-jsonapi-resources' spec.version = JSONAPI::Resources::VERSION - spec.authors = ['Dan Gebhardt', 'Larry Gebhardt'] - spec.email = ['dan@cerebris.com', 'larry@cerebris.com'] + spec.authors = ['PSD Team - Wellcome Trust Sanger Institute'] + spec.email = ['psd@sanger.ac.uk'] spec.summary = 'Easily support JSON API in Rails.' - spec.description = 'A resource-centric approach to implementing the controllers, routes, and serializers needed to support the JSON API spec.' - spec.homepage = 'https://github.com/cerebris/jsonapi-resources' + spec.description = 'Forked from jsonapi-resources. A resource-centric approach to implementing the controllers, routes, and serializers needed to support the JSON API spec.' + spec.homepage = 'https://github.com/sanger/jsonapi-resources' spec.license = 'MIT' spec.files = Dir.glob("{bin,lib}/**/*") + %w(LICENSE.txt README.md) diff --git a/lib/jsonapi/resources/version.rb b/lib/jsonapi/resources/version.rb index fb4178797..26eda26ad 100644 --- a/lib/jsonapi/resources/version.rb +++ b/lib/jsonapi/resources/version.rb @@ -1,5 +1,5 @@ module JSONAPI module Resources - VERSION = '0.11.0.beta1' + VERSION = '0.2.0' end end From d999a78b11faa61e0ed2f8b6032119f3fccfaf5b Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 11:03:00 +0100 Subject: [PATCH 10/70] Add wrapper file for sanger-jsonapi-resources to ensure compatibility with RubyGems --- lib/sanger-jsonapi-resources.rb | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 lib/sanger-jsonapi-resources.rb diff --git a/lib/sanger-jsonapi-resources.rb b/lib/sanger-jsonapi-resources.rb new file mode 100644 index 000000000..2b4763cf6 --- /dev/null +++ b/lib/sanger-jsonapi-resources.rb @@ -0,0 +1,7 @@ +# As we are packaging 'sanger-jsonapi-resources' as a separate gem, RubyGems expects +# the main file to be 'lib/sanger-jsonapi-resources.rb' to match the gem name. +# Without this file, requiring the gem or Rails autoloading would fail, even if the internal code is unchanged. +# This file exists to ensure compatibility with RubyGems and Bundler. +# The easiest solution is to use this wrapper file, which simply requires the original 'jsonapi-resources' code, +# so all internal references and modules remain unchanged and compatible. +require_relative 'jsonapi-resources' From 3100a4b4c4b211c78c56bcf30d89cae4fa7870fb Mon Sep 17 00:00:00 2001 From: Seena Nair <55585488+seenanair@users.noreply.github.com> Date: Wed, 18 Jun 2025 15:01:48 +0100 Subject: [PATCH 11/70] Add Ruby 3.4 to CI matrix for testing compatibility --- .github/workflows/ruby.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 0fe41e0c2..8fd0da3c2 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -13,6 +13,7 @@ jobs: fail-fast: false matrix: ruby: + - '3.4' - '3.3' - '3.2' rails: From 54e8f6938bac6a5e6f8a10230b6f619ac38673f1 Mon Sep 17 00:00:00 2001 From: yoldas Date: Tue, 16 Sep 2025 23:59:12 +0100 Subject: [PATCH 12/70] Add compatibility for obsolete Rack status symbols --- lib/jsonapi/error.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/error.rb b/lib/jsonapi/error.rb index 12d65f585..8eeb87cff 100644 --- a/lib/jsonapi/error.rb +++ b/lib/jsonapi/error.rb @@ -17,7 +17,7 @@ def initialize(options = {}) @source = options[:source] @links = options[:links] - @status = Rack::Utils::SYMBOL_TO_STATUS_CODE[options[:status]].to_s + @status = Rack::Utils.status_code(options[:status]).to_s @meta = options[:meta] end From a098867b0d7254c6e1d03a06b2fe3223262f1400 Mon Sep 17 00:00:00 2001 From: yoldas Date: Wed, 17 Sep 2025 00:48:28 +0100 Subject: [PATCH 13/70] Change version to 0.2.1 --- lib/jsonapi/resources/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/resources/version.rb b/lib/jsonapi/resources/version.rb index 26eda26ad..ae4b3a9da 100644 --- a/lib/jsonapi/resources/version.rb +++ b/lib/jsonapi/resources/version.rb @@ -1,5 +1,5 @@ module JSONAPI module Resources - VERSION = '0.2.0' + VERSION = '0.2.1' end end From fe5e1f1d06fc03dcabfd3bccdf3f1fea728a4719 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:26:55 +0000 Subject: [PATCH 14/70] Rails 8.1 fix --- lib/jsonapi/routing_ext.rb | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index b0b940138..8302fc63f 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -47,27 +47,14 @@ def jsonapi_resource(*resources, &_block) end resource @resource_type, options do - # :nocov: - if @scope.respond_to? :[]= - # Rails 4 - @scope[:jsonapi_resource] = @resource_type - + # Rails 6+ and 8.1: always use the modern block style + jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do if block_given? yield else jsonapi_relationships end - else - # Rails 5 - jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do - if block_given? - yield - else - jsonapi_relationships - end - end end - # :nocov: end end From c2f0662561d9f8454623c2be3e42f90ec2f1ee88 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:32:40 +0000 Subject: [PATCH 15/70] Rails 8.1 fixes --- lib/jsonapi/routing_ext.rb | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 8302fc63f..6e1753844 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -86,7 +86,6 @@ def jsonapi_resources(*resources, &_block) options.merge!(res.routing_resource_options) options[:param] = :id - options[:path] = format_route(@resource_type) if res.resource_key_type == :uuid @@ -109,26 +108,14 @@ def jsonapi_resources(*resources, &_block) end resources @resource_type, options do - # :nocov: - if @scope.respond_to? :[]= - # Rails 4 - @scope[:jsonapi_resource] = @resource_type + # Rails 6+ and 8.1: always use the modern block style + jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do if block_given? yield else jsonapi_relationships end - else - # Rails 5 - jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do - if block_given? - yield - else - jsonapi_relationships - end - end end - # :nocov: end end From b80866e06267aef41a1a7e04b4bb5e3aa9f7e45b Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:36:03 +0000 Subject: [PATCH 16/70] Debugs --- lib/jsonapi/routing_ext.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 6e1753844..f3e91e777 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -107,6 +107,8 @@ def jsonapi_resources(*resources, &_block) options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') end + p "Options: #{options}" + resources @resource_type, options do # Rails 6+ and 8.1: always use the modern block style jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do From 7086a630b9aa1952e572b4bbeeae14f8bc281414 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:37:01 +0000 Subject: [PATCH 17/70] Debugs --- lib/jsonapi/routing_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index f3e91e777..dbb18d7a0 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -109,7 +109,7 @@ def jsonapi_resources(*resources, &_block) p "Options: #{options}" - resources @resource_type, options do + resources @resource_type, **options do # Rails 6+ and 8.1: always use the modern block style jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do if block_given? From 5b08066e0d3acb3c44ec8eaa514b7e58f8548051 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:39:22 +0000 Subject: [PATCH 18/70] Debugs --- lib/jsonapi/routing_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index dbb18d7a0..6adbb0c1a 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -46,7 +46,7 @@ def jsonapi_resource(*resources, &_block) options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') end - resource @resource_type, options do + resource @resource_type, **options do # Rails 6+ and 8.1: always use the modern block style jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do if block_given? From 2d152709cfc8b8b565b70b1bd1454dab85103d2e Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:41:27 +0000 Subject: [PATCH 19/70] Debugs --- lib/jsonapi/routing_ext.rb | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 6adbb0c1a..937c2f835 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -33,18 +33,18 @@ def jsonapi_resource(*resources, &_block) options.merge!(res.routing_resource_options) options[:path] = format_route(@resource_type) - if options[:except] - options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') - options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') - else - options[:except] = [:new, :edit] - end - - if res._immutable - options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') - options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') - options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') - end + # if options[:except] + # options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') + # options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') + # else + # options[:except] = [:new, :edit] + # end + + # if res._immutable + # options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') + # options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') + # options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') + # end resource @resource_type, **options do # Rails 6+ and 8.1: always use the modern block style @@ -93,19 +93,19 @@ def jsonapi_resources(*resources, &_block) options[:constraints][:id] ||= /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/ end - if options[:except] - options[:except] = Array(options[:except]) - options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') - options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') - else - options[:except] = [:new, :edit] - end - - if res._immutable - options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') - options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') - options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') - end + # if options[:except] + # options[:except] = Array(options[:except]) + # options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') + # options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') + # else + # options[:except] = [:new, :edit] + # end + + # if res._immutable + # options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') + # options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') + # options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') + # end p "Options: #{options}" From 143cc1689ca677a23fc93762b3c6aff52c291fbe Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:46:48 +0000 Subject: [PATCH 20/70] Debugs --- lib/jsonapi/routing_ext.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 937c2f835..51070bf1e 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -48,13 +48,13 @@ def jsonapi_resource(*resources, &_block) resource @resource_type, **options do # Rails 6+ and 8.1: always use the modern block style - jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do - if block_given? - yield - else - jsonapi_relationships - end - end + # jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do + # if block_given? + # yield + # else + # jsonapi_relationships + # end + # end end end From 4a7d6668b11cc35cfef73c8b172371145ea7dc4f Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:48:13 +0000 Subject: [PATCH 21/70] Debugs --- lib/jsonapi/routing_ext.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 51070bf1e..49deafd7d 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -46,7 +46,7 @@ def jsonapi_resource(*resources, &_block) # options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') # end - resource @resource_type, **options do + resource @resource_type, options do # Rails 6+ and 8.1: always use the modern block style # jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do # if block_given? @@ -109,15 +109,15 @@ def jsonapi_resources(*resources, &_block) p "Options: #{options}" - resources @resource_type, **options do + resources @resource_type, options do # Rails 6+ and 8.1: always use the modern block style - jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do - if block_given? - yield - else - jsonapi_relationships - end - end + # jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do + # if block_given? + # yield + # else + # jsonapi_relationships + # end + # end end end From 6f2d402d192e43b00f7c3f4631ad00f6f6349a86 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 11:49:15 +0000 Subject: [PATCH 22/70] Debugs --- lib/jsonapi/routing_ext.rb | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 49deafd7d..4c22ada03 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -33,18 +33,18 @@ def jsonapi_resource(*resources, &_block) options.merge!(res.routing_resource_options) options[:path] = format_route(@resource_type) - # if options[:except] - # options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') - # options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') - # else - # options[:except] = [:new, :edit] - # end - - # if res._immutable - # options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') - # options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') - # options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') - # end + if options[:except] + options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') + options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') + else + options[:except] = [:new, :edit] + end + + if res._immutable + options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') + options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') + options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') + end resource @resource_type, options do # Rails 6+ and 8.1: always use the modern block style @@ -93,19 +93,19 @@ def jsonapi_resources(*resources, &_block) options[:constraints][:id] ||= /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/ end - # if options[:except] - # options[:except] = Array(options[:except]) - # options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') - # options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') - # else - # options[:except] = [:new, :edit] - # end - - # if res._immutable - # options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') - # options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') - # options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') - # end + if options[:except] + options[:except] = Array(options[:except]) + options[:except] << :new unless options[:except].include?(:new) || options[:except].include?('new') + options[:except] << :edit unless options[:except].include?(:edit) || options[:except].include?('edit') + else + options[:except] = [:new, :edit] + end + + if res._immutable + options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create') + options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update') + options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') + end p "Options: #{options}" From 5465f91856f4bc40c97246ec2ed06073e6becdbe Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 12:28:49 +0000 Subject: [PATCH 23/70] Debugs --- lib/jsonapi/routing_ext.rb | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 4c22ada03..7e6366c17 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -107,17 +107,14 @@ def jsonapi_resources(*resources, &_block) options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') end - p "Options: #{options}" - resources @resource_type, options do # Rails 6+ and 8.1: always use the modern block style - # jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do - # if block_given? - # yield - # else - # jsonapi_relationships - # end - # end + @jsonapi_resource_type = @resource_type + if block_given? + yield + else + jsonapi_relationships + end end end From 71b84c2e56cf1de9b07dadad01de4a6e49b5040a Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 12:30:30 +0000 Subject: [PATCH 24/70] Debugs --- lib/jsonapi/routing_ext.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 7e6366c17..a7d5048fb 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -109,7 +109,6 @@ def jsonapi_resources(*resources, &_block) resources @resource_type, options do # Rails 6+ and 8.1: always use the modern block style - @jsonapi_resource_type = @resource_type if block_given? yield else From bde2c2a085f22523685c9de4bd852a730de7b846 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 13:04:20 +0000 Subject: [PATCH 25/70] Rails 8.1 compatibility fix --- lib/jsonapi/routing_ext.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index a7d5048fb..c46aef329 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -109,11 +109,13 @@ def jsonapi_resources(*resources, &_block) resources @resource_type, options do # Rails 6+ and 8.1: always use the modern block style + jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do if block_given? yield else jsonapi_relationships end + end end end From fe5f506922fe42ef279fd67d12b0d4064fcb2f69 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 13:13:48 +0000 Subject: [PATCH 26/70] Refactor routing_ext.rb to use modern block style for resource handling --- lib/jsonapi/routing_ext.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index c46aef329..2f2de0d33 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -47,14 +47,13 @@ def jsonapi_resource(*resources, &_block) end resource @resource_type, options do - # Rails 6+ and 8.1: always use the modern block style - # jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do - # if block_given? - # yield - # else - # jsonapi_relationships - # end - # end + jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do + if block_given? + yield + else + jsonapi_relationships + end + end end end From 928771a62476c88f0af4fa25b7238016a037f269 Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 13:14:16 +0000 Subject: [PATCH 27/70] Refactor routing_ext.rb to use modern block style for resource handling --- lib/jsonapi/routing_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 2f2de0d33..52995a336 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -47,7 +47,7 @@ def jsonapi_resource(*resources, &_block) end resource @resource_type, options do - jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], options), @resource_type) do + jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do if block_given? yield else From 4c72d7f0dd7942a42d2fcc902c1854c8d2065f8a Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 13:23:54 +0000 Subject: [PATCH 28/70] Refactor routing_ext.rb to handle Rails version compatibility in resource handling --- lib/jsonapi/routing_ext.rb | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 52995a336..2bc480feb 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -47,13 +47,27 @@ def jsonapi_resource(*resources, &_block) end resource @resource_type, options do - jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do + # :nocov: + if @scope.respond_to? :[]= + # Rails 4 + @scope[:jsonapi_resource] = @resource_type + if block_given? yield else jsonapi_relationships end + else + # Rails 5 + jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do + if block_given? + yield + else + jsonapi_relationships + end + end end + # :nocov: end end @@ -85,6 +99,7 @@ def jsonapi_resources(*resources, &_block) options.merge!(res.routing_resource_options) options[:param] = :id + options[:path] = format_route(@resource_type) if res.resource_key_type == :uuid @@ -107,14 +122,26 @@ def jsonapi_resources(*resources, &_block) end resources @resource_type, options do - # Rails 6+ and 8.1: always use the modern block style - jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do + # :nocov: + if @scope.respond_to? :[]= + # Rails 4 + @scope[:jsonapi_resource] = @resource_type if block_given? yield else jsonapi_relationships end + else + # Rails 5 + jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do + if block_given? + yield + else + jsonapi_relationships + end + end end + # :nocov: end end From cc52b3bb599c9361ca76cba3133b42aebdb2d3af Mon Sep 17 00:00:00 2001 From: Dasun Pubudumal Date: Mon, 26 Jan 2026 13:27:02 +0000 Subject: [PATCH 29/70] Bump version to 0.3.0 --- lib/jsonapi/resources/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/resources/version.rb b/lib/jsonapi/resources/version.rb index ae4b3a9da..b25e5b708 100644 --- a/lib/jsonapi/resources/version.rb +++ b/lib/jsonapi/resources/version.rb @@ -1,5 +1,5 @@ module JSONAPI module Resources - VERSION = '0.2.1' + VERSION = '0.3.0' end end From 33321fad6e0d3dc4b3291f46639344fd072f3257 Mon Sep 17 00:00:00 2001 From: Tom Whiteley Date: Mon, 16 Mar 2026 16:00:28 +0000 Subject: [PATCH 30/70] Adding CONTRIBUTING.md --- CONTRIBUTING.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..03ce14d91 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing + +All contributions to this project are subject to the [MIT License](https://foss-haas.mit-license.org/). By submitting a contribution, you agree to license your work under these terms. + +## Contribution Process + +### 1. Issue First + +All contributions from outside the core team require an **Issue First** approach. Before submitting a pull request (PR), you must: + +- Open an issue in the repository. +- Ensure the issue includes: + - **Clear problem statement:** Describe the issue or feature request. + - **Reproduction steps:** If reporting a bug, provide steps to reproduce it. + - **Proposed approach:** Outline your suggested solution or implementation. + - **Why this change matters:** Explain the impact or necessity of the change. +- Tag `@sanger/psd-developers` in the issue to bring it to the attention of a maintainer. +- Wait for the issue to be assigned or approved by a maintainer. + +### 2. Pull Request + +Once your issue is approved: + +- Fork the repository and create a branch for your changes. +- Submit a PR referencing the approved issue. +- Ensure your code adheres to the project's coding standards and passes all tests. + +### 3. Review + +Maintainers will review your PR. Address any feedback before merging. \ No newline at end of file From 4a9b17537f8a867ce95d4e2a732452eb6730d836 Mon Sep 17 00:00:00 2001 From: Tom Whiteley Date: Wed, 1 Apr 2026 10:52:14 +0100 Subject: [PATCH 31/70] Updating contributing section in README.md to reference CONTRIBUTING.md --- README.md | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/README.md b/README.md index 377e49304..b7f2f18f2 100644 --- a/README.md +++ b/README.md @@ -47,29 +47,7 @@ gem install jsonapi-resources **For further usage see the [v0.10 alpha Guide](http://jsonapi-resources.com/v0.10/guide/)** ## Contributing - -1. Submit an issue describing any new features you wish it add or the bug you intend to fix -1. Fork it ( http://github.com/cerebris/jsonapi-resources/fork ) -1. Create your feature branch (`git checkout -b my-new-feature`) -1. Run the full test suite (`rake test`) -1. Fix any failing tests -1. Commit your changes (`git commit -am 'Add some feature'`) -1. Push to the branch (`git push origin my-new-feature`) -1. Create a new Pull Request - -## Did you find a bug? - -* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/cerebris/jsonapi-resources/issues). - -* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/cerebris/jsonapi-resources/issues/new). -Be sure to include a **title and clear description**, as much relevant information as possible, -and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. - -* If possible, use the relevant bug report templates to create the issue. -Simply copy the content of the appropriate template into a .rb file, make the necessary changes to demonstrate the issue, -and **paste the content into the issue description or attach as a file**: - * [**Rails 5** issues](https://github.com/cerebris/jsonapi-resources/blob/master/lib/bug_report_templates/rails_5_master.rb) - +See CONTRIBUTING.md for details. ## License From 8f9c257ddea963e04ea76e265532215560386ee4 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:23:00 +0100 Subject: [PATCH 32/70] style: lint ci --- .github/workflows/ruby.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 8fd0da3c2..30973df9a 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ 'master' ] + branches: ["master"] pull_request: - branches: ['**'] + branches: ["**"] jobs: tests: @@ -13,13 +13,13 @@ jobs: fail-fast: false matrix: ruby: - - '3.4' - - '3.3' - - '3.2' + - "3.2" + - "3.3" + - "3.4" rails: - - '7.1' - - '7.0' - - '8.0.2' + - "7.0" + - "7.1" + - "8.0.2" database_url: - sqlite3:test_db env: From b284212e4d66537e7997bc837eef00275d8d8cdf Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:20:19 +0100 Subject: [PATCH 33/70] ci: actions/checkout version --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 30973df9a..5c1718d94 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -27,7 +27,7 @@ jobs: DATABASE_URL: ${{ matrix.database_url }} name: Ruby ${{ matrix.ruby }} Rails ${{ matrix.rails }} DB ${{ matrix.database_url }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From 6e868d4fba6c3709c97fba491320b97b8fcce53f Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:21:43 +0100 Subject: [PATCH 34/70] ci: update Rails versions in test matrix --- .github/workflows/ruby.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 5c1718d94..7ec8df04e 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -17,9 +17,9 @@ jobs: - "3.3" - "3.4" rails: - - "7.0" - - "7.1" - - "8.0.2" + - "7.2" + - "8.0" + - "8.1" database_url: - sqlite3:test_db env: From f802996fa35864330f8735ccf6b3c4cbf24a271e Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Fri, 3 Jul 2026 13:34:19 +0100 Subject: [PATCH 35/70] build: update min versions --- Gemfile | 2 +- jsonapi-resources.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index f022a438b..92e208208 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,7 @@ when 'master' gem 'railties', { git: 'https://github.com/rails/rails.git' } gem 'arel', { git: 'https://github.com/rails/arel.git' } when 'default' - gem 'railties', '>= 6.0' + gem 'railties', '~> 8.0.0' else gem 'railties', "~> #{version}" end diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 22745c81d..17581fc99 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.required_ruby_version = '>= 2.3' + spec.required_ruby_version = '>= 3.2' spec.add_development_dependency 'bundler', '>= 1.17' spec.add_development_dependency 'rake' From 9cee43cbb5024c8e966a2c5390f123cdaa6c9b66 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:05:56 +0100 Subject: [PATCH 36/70] build: limit rails versions to 7.2, 8.0+, not including 9+ --- jsonapi-resources.gemspec | 4 ++-- test/test_helper.rb | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 17581fc99..c8cec473b 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'pry' spec.add_development_dependency 'concurrent-ruby-ext' spec.add_development_dependency 'database_cleaner' - spec.add_dependency 'activerecord', '>= 5.1' - spec.add_dependency 'railties', '>= 5.1' + spec.add_dependency 'activerecord', '>= 7.2', '< 9.0' # versions 7.2, 8.0, 8.1, and above, but not 9.0 + spec.add_dependency 'railties', '>= 7.2', '< 9.0' # versions 7.2, 8.0, 8.1, and above, but not 9.0 spec.add_dependency 'concurrent-ruby' end diff --git a/test/test_helper.rb b/test/test_helper.rb index f6f9c1b70..9329a505d 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -65,9 +65,8 @@ class TestApp < Rails::Application config.active_support.halt_callback_chains_on_return_false = false config.active_record.time_zone_aware_types = [:time, :datetime] config.active_record.belongs_to_required_by_default = false - if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR == 2 - config.active_record.sqlite3.represent_boolean_as_integer = true - end + config.active_support.cache_format_version = 7.1 + config.active_support.to_time_preserves_timezone = :zone end DatabaseCleaner.allow_remote_database_url = true From 88487bbd5a00522acbbd29369aa3038518b88ac2 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 10:39:53 +0100 Subject: [PATCH 37/70] build: add rack 2 as a dependency --- jsonapi-resources.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index c8cec473b..697807362 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -29,5 +29,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'database_cleaner' spec.add_dependency 'activerecord', '>= 7.2', '< 9.0' # versions 7.2, 8.0, 8.1, and above, but not 9.0 spec.add_dependency 'railties', '>= 7.2', '< 9.0' # versions 7.2, 8.0, 8.1, and above, but not 9.0 + spec.add_dependency 'rack', '~> 2.0' spec.add_dependency 'concurrent-ruby' end From 41c6eaa72756f41f9255518633eec4d4b2ca35f7 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 11:57:26 +0100 Subject: [PATCH 38/70] release: bump version --- lib/jsonapi/resources/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/resources/version.rb b/lib/jsonapi/resources/version.rb index b25e5b708..f54a58b95 100644 --- a/lib/jsonapi/resources/version.rb +++ b/lib/jsonapi/resources/version.rb @@ -1,5 +1,5 @@ module JSONAPI module Resources - VERSION = '0.3.0' + VERSION = '0.4.0' end end From 8dbb96698709a2808e2549f8e2d112b4711d9ff7 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 14:09:43 +0100 Subject: [PATCH 39/70] test: repair old ruby 2 -> 3 errors --- test/test_helper.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 9329a505d..17bd46b7c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -86,9 +86,9 @@ class Engine < ::Rails::Engine # Monkeypatch ActionController::TestCase to delete the RAW_POST_DATA on subsequent calls in the same test. module ClearRawPostHeader - def process(action, **args) + def process(action, *args, **kwargs) @request.delete_header 'RAW_POST_DATA' - super action, **args + super(action, *args, **kwargs) end end @@ -523,13 +523,13 @@ def assert_cacheable_jsonapi_get(url, cached_classes = :all) end class ActionController::TestCase - def assert_cacheable_get(action, **args) + def assert_cacheable_get(action, **request_options) assert_nil JSONAPI.configuration.resource_cache normal_queries = [] normal_query_callback = lambda {|_, _, _, _, payload| normal_queries.push payload[:sql] } ActiveSupport::Notifications.subscribed(normal_query_callback, 'sql.active_record') do - get action, **args + get action, **request_options end non_caching_response = json_response_sans_all_backtraces non_caching_status = response.status @@ -565,7 +565,7 @@ def assert_cacheable_get(action, **args) @controller = nil setup_controller_request_and_response @request.headers.merge!(orig_request_headers.dup) - get action, **args + get action, **request_options end end rescue Exception From 917c37cf98d80eae78a17585d0e04e099f35fac8 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Fri, 3 Jul 2026 13:58:51 +0100 Subject: [PATCH 40/70] build: add minitest-mock as a development dependency cannot load such file -- minitest/mock (LoadError) --- jsonapi-resources.gemspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 697807362..2883a48df 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -21,7 +21,8 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'bundler', '>= 1.17' spec.add_development_dependency 'rake' - spec.add_development_dependency 'minitest', '~> 5.10', '!= 5.10.2' + spec.add_development_dependency 'minitest' + spec.add_development_dependency 'minitest-mock' spec.add_development_dependency 'minitest-spec-rails' spec.add_development_dependency 'simplecov' spec.add_development_dependency 'pry' From d5afb854bd8c4b77f78633c1d65a3832c17c071e Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 14:02:43 +0100 Subject: [PATCH 41/70] test: repair test runner not being invoked --- test/test_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index 17bd46b7c..53565dfa1 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -24,6 +24,7 @@ require 'active_record/railtie' require 'minitest/mock' +require 'minitest/autorun' require 'jsonapi-resources' require 'pry' From ed2929eacceb5a70419b10c838cf969ee78021d9 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 14:19:15 +0100 Subject: [PATCH 42/70] build: add minitest reporters for better test feedback --- jsonapi-resources.gemspec | 1 + test/test_helper.rb | 3 +++ 2 files changed, 4 insertions(+) diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 2883a48df..643be2e4b 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -24,6 +24,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'minitest' spec.add_development_dependency 'minitest-mock' spec.add_development_dependency 'minitest-spec-rails' + spec.add_development_dependency 'minitest-reporters' spec.add_development_dependency 'simplecov' spec.add_development_dependency 'pry' spec.add_development_dependency 'concurrent-ruby-ext' diff --git a/test/test_helper.rb b/test/test_helper.rb index 53565dfa1..b6e5d3c50 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -25,6 +25,7 @@ require 'active_record/railtie' require 'minitest/mock' require 'minitest/autorun' +require 'minitest/reporters' require 'jsonapi-resources' require 'pry' @@ -33,6 +34,8 @@ require File.expand_path('../helpers/functional_helpers', __FILE__) require File.expand_path('../helpers/configuration_helpers', __FILE__) +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + Rails.env = 'test' I18n.load_path += Dir[File.expand_path("../../locales/*.yml", __FILE__)] From 20f32ecbb1520327db478753964200d47521d4d4 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 14:19:15 +0100 Subject: [PATCH 43/70] test: reduce verbosity of minitest output --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 01619ed8e..791c5171c 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,7 @@ require 'bundler/gem_tasks' require 'rake/testtask' Rake::TestTask.new do |t| - t.verbose = true + t.verbose = false t.warning = false t.test_files = FileList['test/**/*_test.rb'] end From 5ec8202789fe0ec5680acd0cf6cc87315aa6c24d Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Mon, 17 Aug 2026 15:22:50 +0100 Subject: [PATCH 44/70] test: separate rails version text --- test/test_helper.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index b6e5d3c50..04960d61b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -51,7 +51,9 @@ ActiveSupport::Deprecation.silenced = true end +puts "-" * 32 puts "Testing With RAILS VERSION #{Rails.version}" +puts "-" * 32 class TestApp < Rails::Application config.eager_load = false From 1154079565a9aec43b63d507613c0607858151a7 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Wed, 12 Aug 2026 14:33:44 +0100 Subject: [PATCH 45/70] test: ignore temporary test files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 800c71c6a..ba614b629 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,6 @@ coverage test/log test_db test_db-journal +test/test_db-* .idea *.iml From 8ace43f1e26149581a2b68a333937ca01523b088 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Mon, 17 Aug 2026 14:10:21 +0100 Subject: [PATCH 46/70] test: update deprecation warning test --- test/unit/resource/resource_test.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/unit/resource/resource_test.rb b/test/unit/resource/resource_test.rb index df2df1730..1a2ba6c86 100644 --- a/test/unit/resource/resource_test.rb +++ b/test/unit/resource/resource_test.rb @@ -442,7 +442,9 @@ class ProblemResource < JSONAPI::Resource end CODE end - assert_match /DEPRECATION WARNING: Id without format is no longer supported. Please remove ids from attributes, or specify a format./, err + err_msg = /DEPRECATION WARNING: Id without format is no longer supported. Please remove ids from attributes, or specify a format./ + err_msg_rails_8 = /\[DUPLICATE ATTRIBUTE\] `id` has already been defined in ProblemResource\./ + assert(err.match?(err_msg) || err.match?(err_msg_rails_8), "Expected either deprecation or duplicate-attribute warning, got: #{err}") ensure ActiveSupport::Deprecation.silenced = true end From de41a932ab13ab77aa6e0f759e6c0d18c5225eac Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Mon, 17 Aug 2026 14:11:59 +0100 Subject: [PATCH 47/70] fix: use Rails 8 style deprecation warning messages --- lib/jsonapi/compatibility_helper.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/jsonapi/compatibility_helper.rb b/lib/jsonapi/compatibility_helper.rb index 516609349..b1d5266cc 100644 --- a/lib/jsonapi/compatibility_helper.rb +++ b/lib/jsonapi/compatibility_helper.rb @@ -9,8 +9,7 @@ # JSONAPI::CompatibilityHelper.deprecation_warn("Your deprecation message") # # The method will use the public `warn` method if available, otherwise it will -# use `send(:warn, ...)` to maintain compatibility with Rails 8+ where `warn` -# is private. +# use Rails 8+ style deprecation warnings. # # Example: # JSONAPI::CompatibilityHelper.deprecation_warn("This feature is deprecated.") @@ -21,7 +20,7 @@ def deprecation_warn(message) if ActiveSupport::Deprecation.respond_to?(:warn) && ActiveSupport::Deprecation.public_method_defined?(:warn) ActiveSupport::Deprecation.warn(message) else - ActiveSupport::Deprecation.send(:warn, message) + ActiveSupport::Deprecation.new(nil, 'JSONAPI').warn(message) end end module_function :deprecation_warn From 1dab6ce026ac480adadda71b20272af864183bae Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Mon, 17 Aug 2026 15:31:30 +0100 Subject: [PATCH 48/70] fix: improve handling of deprecation warnings --- lib/jsonapi/compatibility_helper.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/jsonapi/compatibility_helper.rb b/lib/jsonapi/compatibility_helper.rb index b1d5266cc..be6379914 100644 --- a/lib/jsonapi/compatibility_helper.rb +++ b/lib/jsonapi/compatibility_helper.rb @@ -17,11 +17,7 @@ module JSONAPI module CompatibilityHelper def deprecation_warn(message) - if ActiveSupport::Deprecation.respond_to?(:warn) && ActiveSupport::Deprecation.public_method_defined?(:warn) - ActiveSupport::Deprecation.warn(message) - else ActiveSupport::Deprecation.new(nil, 'JSONAPI').warn(message) - end end module_function :deprecation_warn end From fd893eafc2b3efc90d2fa9f9d04a08d4a714a693 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Mon, 17 Aug 2026 15:44:51 +0100 Subject: [PATCH 49/70] fix: repair deprecated code --- test/fixtures/active_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixtures/active_record.rb b/test/fixtures/active_record.rb index e6866785c..67fd44362 100644 --- a/test/fixtures/active_record.rb +++ b/test/fixtures/active_record.rb @@ -1679,7 +1679,7 @@ class PlanetResource < JSONAPI::Resource attribute :description has_many :moons - belongs_to :planet_type + has_one :planet_type has_many :tags, acts_as_set: true end From 49b976e8dc1eadc06c1c9c33a4cd7a70f5270860 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:45:53 +0100 Subject: [PATCH 50/70] test: remove test-db as part of the rake task run --- Rakefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Rakefile b/Rakefile index 791c5171c..699237f4b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,13 +1,20 @@ #!/usr/bin/env rake require 'bundler/gem_tasks' +require 'fileutils' require 'rake/testtask' +task :remove_test_db do + FileUtils.rm_f(File.expand_path('test/test_db', __dir__)) +end + Rake::TestTask.new do |t| t.verbose = false t.warning = false t.test_files = FileList['test/**/*_test.rb'] end +Rake::Task[:test].enhance([:remove_test_db]) + task default: [:test] desc 'Run benchmarks' From 3d5dabb9063dee201723e7e5a268131dcfb8c935 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:53:52 +0100 Subject: [PATCH 51/70] build: add test support for Rails 7.1 for overlap with previous release --- .github/workflows/ruby.yml | 1 + jsonapi-resources.gemspec | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 7ec8df04e..f159e5cbd 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -17,6 +17,7 @@ jobs: - "3.3" - "3.4" rails: + - "7.1" - "7.2" - "8.0" - "8.1" diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 643be2e4b..7be374b3d 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -29,8 +29,8 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'pry' spec.add_development_dependency 'concurrent-ruby-ext' spec.add_development_dependency 'database_cleaner' - spec.add_dependency 'activerecord', '>= 7.2', '< 9.0' # versions 7.2, 8.0, 8.1, and above, but not 9.0 - spec.add_dependency 'railties', '>= 7.2', '< 9.0' # versions 7.2, 8.0, 8.1, and above, but not 9.0 + spec.add_dependency 'activerecord', '>= 7.1', '< 9.0' # versions 7.1, 7.2, 8.0, 8.1, and above, but not 9.0 + spec.add_dependency 'railties', '>= 7.1', '< 9.0' # versions 7.1, 7.2, 8.0, 8.1, and above, but not 9.0 spec.add_dependency 'rack', '~> 2.0' spec.add_dependency 'concurrent-ruby' end From 105fb138e22c6734ba27ab32e2ba4cbd10f54ca8 Mon Sep 17 00:00:00 2001 From: Stephen Hulme <135011085+StephenHulme@users.noreply.github.com> Date: Mon, 17 Aug 2026 11:42:28 +0100 Subject: [PATCH 52/70] docs: update README with Sanger release process See #21 --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b7f2f18f2..5f476d520 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -# JSONAPI::Resources [![Gem Version](https://badge.fury.io/rb/jsonapi-resources.svg)](https://badge.fury.io/rb/jsonapi-resources) [![Build Status](https://secure.travis-ci.org/cerebris/jsonapi-resources.svg?branch=master)](http://travis-ci.org/cerebris/jsonapi-resources) [![Code Climate](https://codeclimate.com/github/cerebris/jsonapi-resources/badges/gpa.svg)](https://codeclimate.com/github/cerebris/jsonapi-resources) - -[![Join the chat at https://gitter.im/cerebris/jsonapi-resources](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cerebris/jsonapi-resources?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# JSONAPI::Resources (Sanger fork) `JSONAPI::Resources`, or "JR", provides a framework for developing an API server that complies with the [JSON:API](http://jsonapi.org/) specification. @@ -13,7 +11,7 @@ backed by ActiveRecord models or by custom objects. ## Documentation -Full documentation can be found at [http://jsonapi-resources.com](http://jsonapi-resources.com), including the [v0.10 alpha Guide](http://jsonapi-resources.com/v0.10/guide/) specific to this version. +Full documentation can be found at [http://jsonapi-resources.com](http://jsonapi-resources.com), including the [v0.10 alpha Guide](http://jsonapi-resources.com/v0.10/guide/) specific to this version. ## Demo App @@ -22,31 +20,71 @@ We have a simple demo app, called [Peeps](https://github.com/cerebris/peeps), av ## Client Libraries JSON:API maintains a (non-verified) listing of [client libraries](http://jsonapi.org/implementations/#client-libraries) -which *should* be compatible with JSON:API compliant server implementations such as JR. +which _should_ be compatible with JSON:API compliant server implementations such as JR. ## Installation Add JR to your application's `Gemfile`: -``` +``` gem 'jsonapi-resources' ``` And then execute: -```bash +```bash bundle ``` Or install it yourself as: -```bash +```bash gem install jsonapi-resources ``` **For further usage see the [v0.10 alpha Guide](http://jsonapi-resources.com/v0.10/guide/)** +## Sanger-specific release process + +There are two versions of the gem which we use for production. The version 1 series has unique customisations and is used by Sequencescape. The version 2 series is a more generic version which is used by Traction. + +Check which versions we have published at https://rubygems.org/gems/sanger-jsonapi-resources + +### For version 1 series + +- Create a branch from **develop**, apply fixes. +- Change version number in `lib/jsonapi/resources/version.rb` . This file is read by the gemspec during publication. +- Test Sequencescape with the gem from the branch. +- Merge the branch into develop. +- Create a release from the develop branch with the new version number as the tag. Set Release label to _None_. + +- Checkout the newly-created tag on develop. +- Execute `bundle install` to ensure the gemspec is up to date. +- Execute `gem build jsonapi-resources.gemspec` which builds sanger-jsonapi-resources-0.1.x.gem in this case. +- Execute `gem push sanger-jsonapi-resources-0.1.x.gem` which publishes the gem. + +### For version 2 series + +- Create a branch from **master**, apply fixes. +- Change version number in `lib/jsonapi/resources/version.rb` . This file is read by the gemspec during publication. +- Test Traction with the gem from the branch. +- Merge the branch into master. +- Create a release from the master branch with the new version number as the tag. Set Release label to _Latest_. + +- Checkout the newly-created tag on master. +- Execute `bundle install` to ensure the gemspec is up to date. +- Execute `gem build jsonapi-resources.gemspec` which builds sanger-jsonapi-resources-0.2.x.gem in this case. +- Execute `gem push sanger-jsonapi-resources-0.2.x.gem` which publishes the gem. + +### Publication + +You will be notified by email for each. You will also receive one email for API key setup. The first push will ask email and password for the account, which are in KeePass (search for "gem"). + +> [!NOTE] +> The email and password for gem publication is a recent addition to the credentials database. Pull latest changes in the credentials repo. + ## Contributing + See CONTRIBUTING.md for details. ## License From 805e1772a85756bcac0d09fd513d9316cff36a7b Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 11:57:02 +0100 Subject: [PATCH 53/70] docs: update Rails versions aim --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5f476d520..6c0b80af5 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ gem install jsonapi-resources There are two versions of the gem which we use for production. The version 1 series has unique customisations and is used by Sequencescape. The version 2 series is a more generic version which is used by Traction. +The aim is to support the 3 most recent Rails versions for each series to allow for seamless upgrades between releases. + Check which versions we have published at https://rubygems.org/gems/sanger-jsonapi-resources ### For version 1 series From 6017814ef43c4838154282b6440f48b36bd82949 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 12:02:10 +0100 Subject: [PATCH 54/70] test: use the best reporter for each test environment --- test/test_helper.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 04960d61b..eb8bffc48 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -34,7 +34,12 @@ require File.expand_path('../helpers/functional_helpers', __FILE__) require File.expand_path('../helpers/configuration_helpers', __FILE__) -Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new +if ENV['CI'] == 'true' + # The SpecReporter is easier to read on GitHub + Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new +else + Minitest::Reporters.use! +end Rails.env = 'test' From 346378634f82f8eeade25e82ecdb9dd3e61ab29b Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 12:10:19 +0100 Subject: [PATCH 55/70] test: add patch to Rails version specifier for correct resolution --- Gemfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gemfile b/Gemfile index 92e208208..9a10e270d 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,8 @@ platforms :jruby do end version = ENV['RAILS_VERSION'] || 'default' +# If version is like 'x.y' add a '.0' to make it 'x.y.0' for correct resolution +version = "#{version}.0" if version =~ /^\d+\.\d+$/ platforms :ruby do gem 'pg' From 315d19c057f6e5645b647fb5b98b8fbc69d3d6d9 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 12:47:37 +0100 Subject: [PATCH 56/70] test: file deprecation behaviour silencing for Rails 7.2 --- test/integration/requests/request_test.rb | 4 ++-- test/test_helper.rb | 12 ++++++++---- test/unit/resource/resource_test.rb | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/test/integration/requests/request_test.rb b/test/integration/requests/request_test.rb index 1863b5c7d..165d31e95 100644 --- a/test/integration/requests/request_test.rb +++ b/test/integration/requests/request_test.rb @@ -1367,7 +1367,7 @@ def test_deprecated_include_parameter_not_allowed end def test_deprecated_include_message - ActiveSupport::Deprecation.silenced = false + set_deprecation_behavior(:report) original_config = JSONAPI.configuration.dup _out, err = capture_io do eval <<-CODE @@ -1377,7 +1377,7 @@ def test_deprecated_include_message assert_match /DEPRECATION WARNING: `allow_include` has been replaced by `default_allow_include_to_one` and `default_allow_include_to_many` options./, err ensure JSONAPI.configuration = original_config - ActiveSupport::Deprecation.silenced = true + set_deprecation_behavior(:silence) end diff --git a/test/test_helper.rb b/test/test_helper.rb index eb8bffc48..8bd1bc236 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -50,12 +50,16 @@ config.json_key_format = :camelized_key end -if ActiveSupport::Deprecation.respond_to?(:behavior=) - ActiveSupport::Deprecation.behavior = :silence -elsif ActiveSupport::Deprecation.respond_to?(:silenced=) - ActiveSupport::Deprecation.silenced = true +def set_deprecation_behavior(mode) + if ActiveSupport::Deprecation.respond_to?(:behavior=) + ActiveSupport::Deprecation.behavior = mode + elsif ActiveSupport::Deprecation.respond_to?(:silenced=) + ActiveSupport::Deprecation.silenced = (mode == :silence) + end end +set_deprecation_behavior(:silence) + puts "-" * 32 puts "Testing With RAILS VERSION #{Rails.version}" puts "-" * 32 diff --git a/test/unit/resource/resource_test.rb b/test/unit/resource/resource_test.rb index 1a2ba6c86..464b9049d 100644 --- a/test/unit/resource/resource_test.rb +++ b/test/unit/resource/resource_test.rb @@ -434,7 +434,7 @@ def test_key_type_proc def test_id_attr_deprecation - ActiveSupport::Deprecation.silenced = false + set_deprecation_behavior(:report) _out, err = capture_io do eval <<-CODE class ProblemResource < JSONAPI::Resource @@ -446,7 +446,7 @@ class ProblemResource < JSONAPI::Resource err_msg_rails_8 = /\[DUPLICATE ATTRIBUTE\] `id` has already been defined in ProblemResource\./ assert(err.match?(err_msg) || err.match?(err_msg_rails_8), "Expected either deprecation or duplicate-attribute warning, got: #{err}") ensure - ActiveSupport::Deprecation.silenced = true + set_deprecation_behavior(:silence) end def test_id_attr_with_format From 5bc93eb4083c18a00c253b0e6f663d14241c5dad Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 13:00:16 +0100 Subject: [PATCH 57/70] fix: remove Rails 4 routing --- lib/jsonapi/routing_ext.rb | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index 2bc480feb..daa13d3d9 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -47,27 +47,13 @@ def jsonapi_resource(*resources, &_block) end resource @resource_type, options do - # :nocov: - if @scope.respond_to? :[]= - # Rails 4 - @scope[:jsonapi_resource] = @resource_type - + jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do if block_given? yield else jsonapi_relationships end - else - # Rails 5 - jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do - if block_given? - yield - else - jsonapi_relationships - end - end end - # :nocov: end end @@ -122,26 +108,13 @@ def jsonapi_resources(*resources, &_block) end resources @resource_type, options do - # :nocov: - if @scope.respond_to? :[]= - # Rails 4 - @scope[:jsonapi_resource] = @resource_type + jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do if block_given? yield else jsonapi_relationships end - else - # Rails 5 - jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do - if block_given? - yield - else - jsonapi_relationships - end - end end - # :nocov: end end From 6c55de13739cc5114f8040b24013c76c46930be7 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 13:04:38 +0100 Subject: [PATCH 58/70] fix: add support for keyword options in resources --- lib/jsonapi/routing_ext.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jsonapi/routing_ext.rb b/lib/jsonapi/routing_ext.rb index daa13d3d9..8a37b8246 100644 --- a/lib/jsonapi/routing_ext.rb +++ b/lib/jsonapi/routing_ext.rb @@ -46,7 +46,7 @@ def jsonapi_resource(*resources, &_block) options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') end - resource @resource_type, options do + resource @resource_type, **options do jsonapi_resource_scope(SingletonResource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do if block_given? yield @@ -107,7 +107,7 @@ def jsonapi_resources(*resources, &_block) options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy') end - resources @resource_type, options do + resources @resource_type, **options do jsonapi_resource_scope(Resource.new(@resource_type, api_only?, @scope[:shallow], **options), @resource_type) do if block_given? yield From ad1a4484460c1613458976d82e6297a153df3db7 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Mon, 17 Aug 2026 12:13:06 +0100 Subject: [PATCH 59/70] test: update error message for Rails 8.1 --- test/integration/requests/request_test.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/requests/request_test.rb b/test/integration/requests/request_test.rb index 165d31e95..6ce002c7e 100644 --- a/test/integration/requests/request_test.rb +++ b/test/integration/requests/request_test.rb @@ -578,7 +578,9 @@ def test_put_invalid_json assert_equal 400, status assert_equal 'Bad Request', json_response['errors'][0]['title'] - assert_match 'unexpected token at', json_response['errors'][0]['detail'] + rails_old_msg = 'unexpected token at' + rails_8_1_msg = "expected ',' or '}' after object value, got: '\"attributes\":'" + assert_match (/(#{rails_old_msg}|#{rails_8_1_msg})/), json_response['errors'][0]['detail'] end def test_put_valid_json_but_array From 042816e744701f55bae7b445dc177a7629538ee6 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 13:48:09 +0100 Subject: [PATCH 60/70] test: handle different database True when on SQLite 8.1 --- .../join_manager_test.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/unit/active_relation_resource_finder/join_manager_test.rb b/test/unit/active_relation_resource_finder/join_manager_test.rb index 840c90ee2..e76f1e3c7 100644 --- a/test/unit/active_relation_resource_finder/join_manager_test.rb +++ b/test/unit/active_relation_resource_finder/join_manager_test.rb @@ -4,12 +4,16 @@ class JoinTreeTest < ActiveSupport::TestCase def db_true + rails_major = 8 + rails_minor = 1 + case ActiveRecord::Base.connection.adapter_name when 'SQLite' - if Rails::VERSION::MAJOR >= 6 || (Rails::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 2) - "1" + if Rails::VERSION::MAJOR >= rails_major + 1 || + (Rails::VERSION::MAJOR >= rails_major && ActiveRecord::VERSION::MINOR >= rails_minor) + "TRUE" else - "'t'" + "1" end when 'PostgreSQL' 'TRUE' From ff5107f7725399377b39b883056ee2513eedc8f2 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 13:48:43 +0100 Subject: [PATCH 61/70] build: set development rails to 8.1 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 9a10e270d..1b438ec56 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,7 @@ when 'master' gem 'railties', { git: 'https://github.com/rails/rails.git' } gem 'arel', { git: 'https://github.com/rails/arel.git' } when 'default' - gem 'railties', '~> 8.0.0' + gem 'railties', '~> 8.1.0' else gem 'railties', "~> #{version}" end From 815578cd50c0c01b7663cbff282950fa0d7280ed Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 11:35:55 +0100 Subject: [PATCH 62/70] build: add rack 3 as a dependency --- jsonapi-resources.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsonapi-resources.gemspec b/jsonapi-resources.gemspec index 7be374b3d..52c1f1909 100644 --- a/jsonapi-resources.gemspec +++ b/jsonapi-resources.gemspec @@ -31,6 +31,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'database_cleaner' spec.add_dependency 'activerecord', '>= 7.1', '< 9.0' # versions 7.1, 7.2, 8.0, 8.1, and above, but not 9.0 spec.add_dependency 'railties', '>= 7.1', '< 9.0' # versions 7.1, 7.2, 8.0, 8.1, and above, but not 9.0 - spec.add_dependency 'rack', '~> 2.0' + spec.add_dependency 'rack', '~> 3.0' spec.add_dependency 'concurrent-ruby' end From 11bf1fa47ee8e4a8a9535dfcc5a6ab44e1fb0f98 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 11:38:18 +0100 Subject: [PATCH 63/70] fix: unprocessable_entity -> unprocessable_content --- lib/jsonapi/exceptions.rb | 4 ++-- test/controllers/controller_test.rb | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/jsonapi/exceptions.rb b/lib/jsonapi/exceptions.rb index e917118cf..a0c437eea 100644 --- a/lib/jsonapi/exceptions.rb +++ b/lib/jsonapi/exceptions.rb @@ -498,7 +498,7 @@ def errors def json_api_error(attr_key, message) create_error_object(code: JSONAPI::VALIDATION_ERROR, - status: :unprocessable_entity, + status: :unprocessable_content, title: message, detail: detail(attr_key, message), source: { pointer: pointer(attr_key) }, @@ -532,7 +532,7 @@ def general_error?(attr_key) class SaveFailed < Error def errors [create_error_object(code: JSONAPI::SAVE_FAILED, - status: :unprocessable_entity, + status: :unprocessable_content, title: I18n.translate('jsonapi-resources.exceptions.save_failed.title', default: 'Save failed or was cancelled'), detail: I18n.translate('jsonapi-resources.exceptions.save_failed.detail', diff --git a/test/controllers/controller_test.rb b/test/controllers/controller_test.rb index e2568f979..a2f220664 100644 --- a/test/controllers/controller_test.rb +++ b/test/controllers/controller_test.rb @@ -761,7 +761,7 @@ def test_create_link_to_missing_object } } - assert_response :unprocessable_entity + assert_response :unprocessable_content # TODO: check if this validation is working assert_match /author - can't be blank/, response.body assert_nil response.location @@ -864,7 +864,7 @@ def test_create_with_invalid_data } } - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal "/data/relationships/author", json_response['errors'][0]['source']['pointer'] assert_equal "can't be blank", json_response['errors'][0]['title'] @@ -2019,7 +2019,7 @@ def test_delete_with_validation_error_base assert_equal "can't destroy me", json_response['errors'][0]['title'] assert_equal "/data", json_response['errors'][0]['source']['pointer'] - assert_response :unprocessable_entity + assert_response :unprocessable_content end def test_delete_with_validation_error_attr @@ -2028,7 +2028,7 @@ def test_delete_with_validation_error_attr assert_equal "is locked", json_response['errors'][0]['title'] assert_equal "/data/attributes/title", json_response['errors'][0]['source']['pointer'] - assert_response :unprocessable_entity + assert_response :unprocessable_content end def test_delete_single @@ -2631,7 +2631,7 @@ def test_create_validations_missing_attribute } } - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 2, json_response['errors'].size assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code'] assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][1]['code'] @@ -2653,7 +2653,7 @@ def test_update_validations_missing_attribute } } - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 1, json_response['errors'].size assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code'] assert_match /name - can't be blank/, response.body @@ -3183,7 +3183,7 @@ def test_create_with_invalid_data } } - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal "/data/attributes/spouse-name", json_response['errors'][0]['source']['pointer'] assert_equal "can't be blank", json_response['errors'][0]['title'] @@ -3779,7 +3779,7 @@ def test_save_model_callbacks_fail } } - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_match /Save failed or was cancelled/, json_response['errors'][0]['detail'] end end @@ -4077,7 +4077,7 @@ def test_delete_with_validation_error_base_on_resource assert_equal "can't destroy me", json_response['errors'][0]['title'] assert_equal "/data/attributes/base", json_response['errors'][0]['source']['pointer'] - assert_response :unprocessable_entity + assert_response :unprocessable_content end end From 40961b68001c57c6e607abc216aa45ff3d4dea6a Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 12:48:17 +0100 Subject: [PATCH 64/70] fix: replace updated Rack status_code function with legacy version --- lib/jsonapi/error.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/jsonapi/error.rb b/lib/jsonapi/error.rb index 8eeb87cff..55ea05378 100644 --- a/lib/jsonapi/error.rb +++ b/lib/jsonapi/error.rb @@ -17,7 +17,7 @@ def initialize(options = {}) @source = options[:source] @links = options[:links] - @status = Rack::Utils.status_code(options[:status]).to_s + @status = status_code(options[:status]).to_s @meta = options[:meta] end @@ -48,11 +48,22 @@ def update_with_overrides(error_object_overrides) if error_object_overrides[:status] # :nocov: - @status = Rack::Utils::SYMBOL_TO_STATUS_CODE[error_object_overrides[:status]].to_s + @status = status_code(error_object_overrides[:status]).to_s # :nocov: end @meta = error_object_overrides[:meta] || @meta end + + private + + # Extracted from Rack 2 + def status_code(status) + if status.is_a?(Symbol) + Rack::Utils::SYMBOL_TO_STATUS_CODE.fetch(status) { raise ArgumentError, "Unrecognized status code #{status.inspect}" } + else + status.to_i + end + end end class Warning From 8f9a01c95cf477ab64bd659b281963de3811178e Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Tue, 11 Aug 2026 14:42:57 +0100 Subject: [PATCH 65/70] test: add additional unprocessable content tests --- test/integration/requests/request_test.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/integration/requests/request_test.rb b/test/integration/requests/request_test.rb index 6ce002c7e..b48914afe 100644 --- a/test/integration/requests/request_test.rb +++ b/test/integration/requests/request_test.rb @@ -453,6 +453,9 @@ def test_post_single_minimal_invalid } assert_jsonapi_response 422 + assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code'] + assert_equal '422', json_response['errors'][0]['status'] + assert_match "can't be blank", json_response['errors'][0]['title'] end def test_update_relationship_without_content_type From 5f5149f4bfba040fc33f56c85c2a76d5d24d8b2f Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Wed, 12 Aug 2026 14:30:10 +0100 Subject: [PATCH 66/70] test: add json-api error tests --- .../jsonapi_request/jsonapi_error_test.rb | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/unit/jsonapi_request/jsonapi_error_test.rb diff --git a/test/unit/jsonapi_request/jsonapi_error_test.rb b/test/unit/jsonapi_request/jsonapi_error_test.rb new file mode 100644 index 000000000..078971d8c --- /dev/null +++ b/test/unit/jsonapi_request/jsonapi_error_test.rb @@ -0,0 +1,41 @@ +require File.expand_path('../../../test_helper', __FILE__) + +class JSONAPIErrorTest < Minitest::Test + def test_status_code_no_status + error = JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST) + + assert_equal('0', error.status) + end + + def test_status_code_accepts_symbol + error = JSONAPI::Error.new(code: JSONAPI::VALIDATION_ERROR, status: :unprocessable_content) + + assert_equal('422', error.status) + end + + def test_status_code_accepts_integer + error = JSONAPI::Error.new(code: JSONAPI::VALIDATION_ERROR, status: 422) + + assert_equal('422', error.status) + end + + def test_status_code_accepts_string + error = JSONAPI::Error.new(code: JSONAPI::VALIDATION_ERROR, status: '422') + + assert_equal('422', error.status) + end + + def test_status_code_rejects_unknown_symbol + error = assert_raises(ArgumentError) do + JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST, status: :not_a_real_status) + end + + assert_equal('Unrecognized status code :not_a_real_status', error.message) + end + + def test_status_code_handles_nil + error = JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST, status: nil) + + assert_equal('0', error.status) + end +end From 2b1943a3a394e983f188d9581b121f6a74835be6 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Wed, 12 Aug 2026 14:35:03 +0100 Subject: [PATCH 67/70] fix: raise ArgumentError for nil status --- lib/jsonapi/error.rb | 4 ++++ test/unit/jsonapi_request/jsonapi_error_test.rb | 16 ++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/jsonapi/error.rb b/lib/jsonapi/error.rb index 55ea05378..9e23d30ca 100644 --- a/lib/jsonapi/error.rb +++ b/lib/jsonapi/error.rb @@ -58,6 +58,10 @@ def update_with_overrides(error_object_overrides) # Extracted from Rack 2 def status_code(status) + if status.nil? + raise ArgumentError, "Status code is required" + end + if status.is_a?(Symbol) Rack::Utils::SYMBOL_TO_STATUS_CODE.fetch(status) { raise ArgumentError, "Unrecognized status code #{status.inspect}" } else diff --git a/test/unit/jsonapi_request/jsonapi_error_test.rb b/test/unit/jsonapi_request/jsonapi_error_test.rb index 078971d8c..801b8204d 100644 --- a/test/unit/jsonapi_request/jsonapi_error_test.rb +++ b/test/unit/jsonapi_request/jsonapi_error_test.rb @@ -1,10 +1,12 @@ require File.expand_path('../../../test_helper', __FILE__) class JSONAPIErrorTest < Minitest::Test - def test_status_code_no_status - error = JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST) + def test_status_code_requires_status + error = assert_raises(ArgumentError) do + JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST) + end - assert_equal('0', error.status) + assert_equal('Status code is required', error.message) end def test_status_code_accepts_symbol @@ -33,9 +35,11 @@ def test_status_code_rejects_unknown_symbol assert_equal('Unrecognized status code :not_a_real_status', error.message) end - def test_status_code_handles_nil - error = JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST, status: nil) + def test_status_code_rejects_nil + error = assert_raises(ArgumentError) do + JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST, status: nil) + end - assert_equal('0', error.status) + assert_equal('Status code is required', error.message) end end From e2add4f98659d1857b8a5d23a8385b74ca50ca82 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 13:52:59 +0100 Subject: [PATCH 68/70] release: bump patch version --- lib/jsonapi/resources/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/resources/version.rb b/lib/jsonapi/resources/version.rb index f54a58b95..32ebf10d8 100644 --- a/lib/jsonapi/resources/version.rb +++ b/lib/jsonapi/resources/version.rb @@ -1,5 +1,5 @@ module JSONAPI module Resources - VERSION = '0.4.0' + VERSION = '0.4.1' end end From 00eb7def4ef19565a9b958ae07eac20195b232f4 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 14:25:35 +0100 Subject: [PATCH 69/70] ci: add Ruby 4 to test matrix --- .github/workflows/ruby.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index f159e5cbd..c5de44418 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -16,6 +16,7 @@ jobs: - "3.2" - "3.3" - "3.4" + - "4.0" rails: - "7.1" - "7.2" From f66d9673a2ba87036d4ea1adecc9cb988b09a353 Mon Sep 17 00:00:00 2001 From: Stephen Hulme Date: Thu, 20 Aug 2026 14:25:41 +0100 Subject: [PATCH 70/70] release: bump patch version --- lib/jsonapi/resources/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonapi/resources/version.rb b/lib/jsonapi/resources/version.rb index 32ebf10d8..401a9449c 100644 --- a/lib/jsonapi/resources/version.rb +++ b/lib/jsonapi/resources/version.rb @@ -1,5 +1,5 @@ module JSONAPI module Resources - VERSION = '0.4.1' + VERSION = '0.4.2' end end