diff --git a/lib/tapioca/dsl/compilers/job_iteration.rb b/lib/tapioca/dsl/compilers/job_iteration.rb index 830e54b3..1e6b79df 100644 --- a/lib/tapioca/dsl/compilers/job_iteration.rb +++ b/lib/tapioca/dsl/compilers/job_iteration.rb @@ -10,6 +10,7 @@ class JobIteration < Compiler extend T::Sig ConstantType = type_member { { fixed: T.class_of(::JobIteration::Iteration) } } + ParamTypesInOrder = [RBI::Param, RBI::OptParam, RBI::RestParam, RBI::KwParam, RBI::KwOptParam, RBI::KwRestParam, RBI::BlockParam].freeze sig { override.void } def decorate @@ -29,7 +30,11 @@ def decorate expanded_parameters = parameters.flat_map do |typed_param| if (hash_type = fixed_hash_args[typed_param.param.name.to_sym]) hash_type.types.map do |key, value| - create_kw_param(key.to_s, type: value.to_s) + if value.name.start_with?("T.nilable") + create_kw_opt_param(key.to_s, type: value.to_s, default: "nil") + else + create_kw_param(key.to_s, type: value.to_s) + end end else typed_param @@ -39,6 +44,8 @@ def decorate expanded_parameters = parameters end + expanded_parameters.sort_by! { |typed_param| ParamTypesInOrder.index(typed_param.param.class) } + job.create_method( "perform_later", parameters: perform_later_parameters(expanded_parameters, constant_name), diff --git a/test/tapioca/dsl/compilers/job_iteration_test.rb b/test/tapioca/dsl/compilers/job_iteration_test.rb index 5bc8cce3..0bfd44c6 100644 --- a/test/tapioca/dsl/compilers/job_iteration_test.rb +++ b/test/tapioca/dsl/compilers/job_iteration_test.rb @@ -271,6 +271,45 @@ def perform_now(user_id:, name:); end assert_equal(expected, rbi_for(:NotifyJob)) end + def test_generates_nil_default_value_for_nilable_parameters + add_ruby_file("job.rb", <<~RUBY) + class NotifyJob < ActiveJob::Base + include JobIteration::Iteration + + Params = T.type_alias { { user_id: T.nilable(Integer), name: String } } + + extend T::Sig + sig { params(params: Params, cursor: T.untyped).returns(T::Array[T.untyped]) } + def build_enumerator(params, cursor:) + # ... + end + end + RUBY + + expected = template(<<~RBI) + # typed: strong + + class NotifyJob + sig { params(name: ::String, user_id: T.nilable(::Integer)).void } + def perform(name:, user_id: nil); end + + class << self + <% if rails_version(">= 7.0") %> + sig { params(name: ::String, user_id: T.nilable(::Integer), block: T.nilable(T.proc.params(job: NotifyJob).void)).returns(T.any(NotifyJob, FalseClass)) } + def perform_later(name:, user_id: nil, &block); end + <% else %> + sig { params(name: ::String, user_id: T.nilable(::Integer)).returns(T.any(NotifyJob, FalseClass)) } + def perform_later(name:, user_id: nil); end + <% end %> + + sig { params(name: ::String, user_id: T.nilable(::Integer)).returns(T.any(NilClass, Exception)) } + def perform_now(name:, user_id: nil); end + end + end + RBI + assert_equal(expected, rbi_for(:NotifyJob)) + end + def test_generates_correct_rbi_file_for_job_with_build_enumerator_method_with_nested_hash_parameter add_ruby_file("job.rb", <<~RUBY) class ResourceType; end