I’m wondering what the general best practice is about accessing external data state from contracts is, particularly data which is stored in a database or external system.
Let me provide a contrived example:
class CreateChargeContract params do required(:fund_source_id).filled(:string) required(:currency).filled(:string) required(:amount).filled(:integer) end rule(:currency) do fund_source = FundSource.find(fund_source_id) key.failure(:unsupported) unless fund_source.supports_currency?(value) end end
Here, our contract requires a trip to the database to retrieve a
FundSource object, which is required to verify that the supplied
currency value is supported.
However, it doesn’t make sense to for the contract to be responsible for retrieving this information in this way. Notably, other parts of the system may also need to retrieve this
FundSource object (to perform authorization, or to access other information) which would cause redundant trips to the DB. If the way forward is to fetch the record from within the contract, I’d prefer a way of retrieving that object after it has been fetched.
That being said, there doesn’t seem to be any mention in the documentation about storing other objects within contracts, outside of their input parameters.
Similarly, I wasn’t able to find any way of passing the
FundSource into this contract, beyond defining plain-old Ruby attributes (which I’m not sure is the idiomatic way of doing things).
What would be the best way to approach this sort of problem?