-
Notifications
You must be signed in to change notification settings - Fork 155
Closed
Description
#2421 updated the ActiveRecord relations compiler to generate signatures for #upsert and #upsert_all (as well as many other methods). Howver, the signatures are incorrect:
sig do
params(
attributes: Hash,
returning: T.nilable(T.any(T::Array[Symbol], FalseClass)),
unique_by: T.nilable(T.any(T::Array[Symbol], Symbol))
).returns(ActiveRecord::Result)
end
def upsert(attributes, returning: nil, unique_by: nil); end
sig do
params(
attributes: T::Array[Hash],
returning: T.nilable(T.any(T::Array[Symbol], FalseClass)),
unique_by: T.nilable(T.any(T::Array[Symbol], Symbol))
).returns(ActiveRecord::Result)
end
def upsert_all(attributes, returning: nil, unique_by: nil); endThere are multiple issues:
-
The signatures are missing some valid arguments:
on_duplicate,update_only, andrecord_timestamps(cf. Rails docs and source) -
returningis typed asT.nilable(T.any(T::Array[Symbol], FalseClass)), but it can also be aStringor aT::Array[String]. Some examples:Commodity.upsert_all( [ { id: 2, name: "Copper", price: 4.84, created_at: Time.now, updated_at: Time.now }, { id: 4, name: "Gold", price: 1380.87, created_at: Time.now, updated_at: Time.now }, { id: 8, name: "Steel", price: 1.35, created_at: Time.now, updated_at: Time.now } ], returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name") # Arel.sql returns a String ) Commodity.upsert_all( [ { id: 2, name: "Copper", price: 4.84, created_at: Time.now, updated_at: Time.now }, { id: 4, name: "Gold", price: 1380.87, created_at: Time.now, updated_at: Time.now }, { id: 8, name: "Steel", price: 1.35, created_at: Time.now, updated_at: Time.now } ], on_duplicate: Arel.sql("price = GREATEST(commodities.price, EXCLUDED.price)"), returning: ["price"] # Need to use String to reference dynamic SQL "columns" )
I'm also curious why these signatures were added to the compiler in the first place. Since they don't reference the model class, it seems like they could be omitted from the compiler and handled via annotations for ActiveRecord instead.
Metadata
Metadata
Assignees
Labels
No labels