Shopify/tapioca

Incorrect array signature for `.new` in ActiveRecord model

jcollins-gc opened this issue · 2 comments

An incorrect signature is being generated for the .new method in an ActiveRecord model.

Even though the .new method does not support arrays, this signature is nevertheless being generated:

    sig do
      params(
        attributes: T::Array[T.untyped],
        block: T.nilable(T.proc.params(object: ::Payment).void)
      ).returns(T::Array[::Payment])
    end

This is despite arrays not being supported in the .new method:

[1] > Payment.new([])
ArgumentError: When assigning attributes, you must pass a hash as an argument, Array passed.

Suspect commit: https://github.com/Shopify/tapioca/pull/1946/files#diff-ccd1794e49448cc1badb48d2a32af60d5fcd47336d00a484fbf474ebf79b6789R223

We have a similar issue, probably also caused by the suspect commit linked in the original post. After regenerating types, sorbet is giving us multiple errors with the same pattern: method <x> does not exist on T::Array[<model>], where the underlying type should obviously resolve to <model> - all type mismatches originate from builder methods of AR (#create, #build). Even after checking out the recent fix commit df6e272

I investigated further:

  # no signature -> returns T.untyped
  def some_params
    { company_id:, data: permitted_params.merge({ scheduling_user_id: current_user.id }) }
  end

  Model.create!(some_params) # revealed type is `T::Array[Model]`

Typing attributes works:

  sig { returns(T::Hash[Symbol, T.untyped]) }
  def some_params
    { company_id:, data: permitted_params.merge({ scheduling_user_id: current_user.id }) }
  end

  Model.create!(some_params) # revealed type is `Model`

Splatting attributes also helps:

  def some_params
    { company_id:, data: permitted_params.merge({ scheduling_user_id: current_user.id }) }
  end

  Model.create!(**some_params) # revealed type is `Model`

@pawelduda it's a side effect of this feature #1978 combined with Sorbet's prioritization which is outlined in sorbet/sorbet#7744. I suggest typing the arguments supplied.