diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c36d729..cbb753b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,6 +28,15 @@ jobs: rails: '~> 8.0.0' - ruby: '3.4' rails: '~> 8.0.0' + - ruby: '4.0' + rails: '~> 8.0.0' + - ruby: '3.3' + rails: '~> 8.1.0' + - ruby: '3.4' + rails: '~> 8.1.0' + - ruby: '4.0' + rails: '~> 8.1.0' + steps: - uses: actions/checkout@v5 @@ -39,6 +48,7 @@ jobs: - name: Set Rails version run: | echo "RAILS_VERSION=${{ matrix.rails }}" >> $GITHUB_ENV + echo "RUBY_VERSION=${{ matrix.ruby }}" >> $GITHUB_ENV - name: Install dependencies run: | bundle install --jobs 4 --retry 3 diff --git a/.rubocop.yml b/.rubocop.yml index 1a7561a..f7a8af6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,6 @@ plugins: - rubocop-rspec - rubocop-rake - - rubocop-rbs_inline - rubocop-factory_bot AllCops: @@ -27,5 +26,5 @@ RSpec/ExampleLength: Metrics/ClassLength: Max: 150 - Metrics/MethodLength: +Metrics/MethodLength: Max: 20 diff --git a/.rubocop_rbs.yml b/.rubocop_rbs.yml new file mode 100644 index 0000000..a81a9f5 --- /dev/null +++ b/.rubocop_rbs.yml @@ -0,0 +1,9 @@ +# RuboCop configuration for Ruby 3.3+ with RBS Inline support +inherit_from: .rubocop.yml + +plugins: + - rubocop-rbs_inline + +# ========= RBS =========== +Style/RbsInline/MissingTypeAnnotation: + EnforcedStyle: method_type_signature diff --git a/.ruby-version b/.ruby-version index 4f5e697..fcdb2e1 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.5 +4.0.0 diff --git a/Gemfile b/Gemfile index 417ccdd..f27bc04 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled source 'https://rubygems.org' @@ -22,13 +23,17 @@ group :development, :test do gem 'factory_bot' gem 'lefthook', require: false gem 'rake', '~> 13.0' - gem 'rbs-inline', require: false gem 'rspec', '~> 3.0' gem 'rspec-parameterized' gem 'rubocop' gem 'rubocop-factory_bot', require: false gem 'rubocop-rake', require: false - gem 'rubocop-rbs_inline', require: false gem 'rubocop-rspec', require: false - gem 'steep', require: false + + # rbs-inline requires Ruby 3.3+ + if RUBY_VERSION >= '3.3.0' + gem 'rbs-inline', require: false + gem 'rubocop-rbs_inline', require: false + gem 'steep', require: false + end end diff --git a/Rakefile b/Rakefile index 0e0b70f..af5a5d4 100644 --- a/Rakefile +++ b/Rakefile @@ -1,14 +1,31 @@ # frozen_string_literal: true +# rbs_inline: enabled require 'bundler/gem_tasks' require 'rspec/core/rake_task' -require 'steep/rake_task' RSpec::Core::RakeTask.new(:spec) require 'rubocop/rake_task' -RuboCop::RakeTask.new -Steep::RakeTask.new +# Use RBS Inline configuration for Ruby 3.3+ +rubocop_config = if RUBY_VERSION >= '3.3.0' + '.rubocop_rbs.yml' + else + '.rubocop.yml' + end -task default: %i[spec rubocop steep] +RuboCop::RakeTask.new do |task| + task.options = ['--config', rubocop_config] +end + +# Steep is only available for Ruby 3.3+ +default_tasks = %i[spec rubocop] + +if RUBY_VERSION >= '3.3.0' + require 'steep/rake_task' + Steep::RakeTask.new + default_tasks << :steep +end + +task default: default_tasks diff --git a/Steepfile b/Steepfile index 6309f26..8eb0ac3 100644 --- a/Steepfile +++ b/Steepfile @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # D = Steep::Diagnostic target :lib do diff --git a/bin/console b/bin/console index fef4850..4fdf31d 100755 --- a/bin/console +++ b/bin/console @@ -1,5 +1,6 @@ #!/usr/bin/env ruby # frozen_string_literal: true +# rbs_inline: enabled require 'bundler/setup' require 'structured_params' diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 0000000..0ae32c8 --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# rbs_inline: enabled + +# Wrapper script for rubocop that automatically uses the correct config file +# based on Ruby version + +config_file = if RUBY_VERSION >= '3.3.0' && File.exist?('.rubocop_rbs.yml') + '.rubocop_rbs.yml' + else + '.rubocop.yml' + end + +exec('bundle', 'exec', 'rubocop', '--config', config_file, *ARGV) diff --git a/lib/structured_params/params.rb b/lib/structured_params/params.rb index 834e9f1..c8e8b7e 100644 --- a/lib/structured_params/params.rb +++ b/lib/structured_params/params.rb @@ -18,7 +18,7 @@ class Params # @rbs @errors: ::StructuredParams::Errors? class << self - # @rbs self.@structured_attributes: Hash[Symbol, singleton(::StructuredParams::Params)]? + # @rbs @structured_attributes: Hash[Symbol, singleton(::StructuredParams::Params)]? # Generate permitted parameter structure for Strong Parameters #: () -> Array[untyped] @@ -128,9 +128,7 @@ def validate_structured_parameters end # Validate structured arrays - # @rbs attr_name: Symbol - # @rbs array_value: Array[untyped] - # @rbs return: void + #: (Symbol, Array[untyped]) -> void def validate_structured_array(attr_name, array_value) array_value.each_with_index do |item, index| next if item.valid?(validation_context) @@ -141,9 +139,7 @@ def validate_structured_array(attr_name, array_value) end # Validate structured objects - # @rbs attr_name: Symbol - # @rbs object_value: ::StructuredParams::Params - # @rbs return: void + #: (Symbol, StructuredParams::Params) -> void def validate_structured_object(attr_name, object_value) return if object_value.valid?(validation_context) diff --git a/lib/structured_params/type/object.rb b/lib/structured_params/type/object.rb index b1d22d4..645f313 100644 --- a/lib/structured_params/type/object.rb +++ b/lib/structured_params/type/object.rb @@ -10,6 +10,7 @@ class Object < ActiveModel::Type::Value # Get permitted parameter names for use with Strong Parameters # @rbs! # def permit_attribute_names: () -> ::Array[untyped] + delegate :permit_attribute_names, to: :value_class #: (value_class: singleton(StructuredParams::Params), **untyped) -> void diff --git a/spec/errors_spec.rb b/spec/errors_spec.rb index a23d234..52640ef 100644 --- a/spec/errors_spec.rb +++ b/spec/errors_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled require 'spec_helper' diff --git a/spec/factories/address_parameters.rb b/spec/factories/address_parameters.rb index c7e3127..6cbf531 100644 --- a/spec/factories/address_parameters.rb +++ b/spec/factories/address_parameters.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled class AddressParameter < StructuredParams::Params attribute :postal_code, :string diff --git a/spec/factories/hobby_parameters.rb b/spec/factories/hobby_parameters.rb index f9c4c3f..4385f5b 100644 --- a/spec/factories/hobby_parameters.rb +++ b/spec/factories/hobby_parameters.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled class HobbyParameter < StructuredParams::Params attribute :name, :string diff --git a/spec/factories/user_parameters.rb b/spec/factories/user_parameters.rb index 5d27d1f..c234127 100644 --- a/spec/factories/user_parameters.rb +++ b/spec/factories/user_parameters.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled class UserParameter < StructuredParams::Params attribute :name, :string diff --git a/spec/params_spec.rb b/spec/params_spec.rb index b45cd98..fd06cc3 100644 --- a/spec/params_spec.rb +++ b/spec/params_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled require 'spec_helper' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7b65c79..4ef9364 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled require 'structured_params' require 'rspec-parameterized' diff --git a/spec/type/array_spec.rb b/spec/type/array_spec.rb index 6cd731a..a31473d 100644 --- a/spec/type/array_spec.rb +++ b/spec/type/array_spec.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true +# rbs_inline: enabled require 'spec_helper' RSpec.describe StructuredParams::Type::Array do let(:dummy_model_class) do Class.new(StructuredParams::Params) do + #: () -> String def self.name 'DummyModel' end diff --git a/spec/type/object_spec.rb b/spec/type/object_spec.rb index 42dde0f..694546b 100644 --- a/spec/type/object_spec.rb +++ b/spec/type/object_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled require 'spec_helper' @@ -7,6 +8,7 @@ let(:dummy_model_class) do Class.new(StructuredParams::Params) do + #: () -> String def self.name 'DummyModel' end diff --git a/structured_params.gemspec b/structured_params.gemspec index 5a3672a..82b241c 100644 --- a/structured_params.gemspec +++ b/structured_params.gemspec @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled require_relative 'lib/structured_params/version' @@ -12,7 +13,7 @@ Gem::Specification.new do |spec| spec.description = '' spec.homepage = 'https://github.com/Syati/structured_params' spec.license = 'MIT' - spec.required_ruby_version = '>= 3.0.0' + spec.required_ruby_version = '>= 3.2.0' spec.require_paths = ['lib'] spec.files = Dir[ 'LICENSE.txt',