Have an option on ActiveRecord::Create to trust inputs rather than running queries to ensure relations exist

I think it would be really cool to have a flag or method so I could tell ActiveRecord to be more trusting of my input. The specific example is that if I am passing an ID of a related model, I’d like ActiveRecord to trust me that it is there, rather than executing a database call to prove it. I wonder if it could be called trust_relations or something similar.

I realise this is a bit of a weird suggestion. I hope this example helps.

Imagine an Item model which belongs_to :account. So we have an Account model.

Imagine a POST /item endpoint which is protected by an access token. I have some code somewhere else (maybe in a different microservice) which has pulled the access token, and extracted an account_id. So my code is being told ‘create an item with these properties, for account_id AC123’.

What currently happens is if I try to create the model

Item.create!(data: data, account_id: "AC123")

I get a SQL trace

SELECT "accounts".* FROM "accounts" WHERE "account"."id" = $1 LIMIT $2
INSERT INTO "items" ("account_id", "data", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"

but what I’d like is to be able to manually tell ActiveRecord ’ I am 99.9% sure that the account with that ID exists. And I’m happy to let my database explode (I have a foreign key constraint) if it doesn’t. So just run the insert please (i.e. don’t bother with the select).

Reasons to do this

  • it could make more write-only routes more performant
  • it would remove various strange bits of code which I have seen that are designed to try and avoid that extra db call

Reasons not to do this

  • 99% of the time, that record is in memory so the DB call is very cheap
  • if you don’t have a foreign key constraint in your database and use this option / method, it’s a footgun that can really hurt you

Another reason not to do this: what if your authorization scheme uses the parent object to determine if you can access/list/change the children. Then you’re really going to want the database lookup and all that goes with it, so that you have a real reference to an object that you can further inspect to see if it is allowed to proceed.

Walter

So there are obviously many reasons when you would not want to use this feature, including:

  1. if you don’t have db protection (e.g. foreign key constraint)
  2. if you have low confidence in the input data (e.g. user input) - even with a db constraint running the SELECT is a lot cheaper than dealing with the fallout from the db error
  3. if you need the relation for any reason (e.g. to denormalise other information, perform model validation, or validate the request)

But I think those (including that suggested by walter) are reasons why you shouldn’t use it, rather than reasons why we shouldn’t provide the option?

I think in the case walter describes, it would be pretty obvious to the developer that this option is not appropriate (I would hope), particularly if we document it properly?