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.