I’m currently writing code to import royalty data from our distributor. In comes in the form of 28 or so spreadsheets (because, of course it does). For each, the first step is to upload and ingest it. And, because I’m paranoid about getting royalties correct, I try to do a bunch of validation and reconciliation as I read each sheet in.The typical flow is:Extract the spreadsheet file from the incoming HTTP request.Extract metadata from the file and use it to start populating an Upload record, where I keep track of each upload, regardless of its content.Parse the spreadsheet, extracting the data I need. Sometimes this is easy; it’s just a table. Other times the data is more like a statement or invoice, with a variable format, so I have an actual parser to understand it.I then associate the data to do with an actual title with the title in our database.Finally, I save all the data, typically across three or four tables, in a single transaction. These steps are basically a pipeline, where each step feeds data to the next. However, errors can happen at each step, and I need to record them in the Upload record. When an error occurs, I stop processing that spreadsheet. This means I can’t use regular Ruby pipelines.Each step returns a hash, either { status: :ok, data: data_to_pass_to_next_step } or { status: :error, message: error_reason }. Here are the three alternative designs I played with.Why overthink it? Just write the code:result = excel_file_attached?(file) if result[:status] == :error record_error(upload, result[:message]) else result = add_details_to_upload(result[:data], upload) if result[:status] == :error record_error(upload, result[:message]) else result = parse_statement(result[:data]) if result[:status] == :error record_error(upload, result[:message]) else result = map_isbns_to_skus(result[:data]) if result[:status] == :error record_error(result[:message], upload) else result = save_rows(upload, result[:data]) end end end endCode like this hurts my soul, so ...
First seen: 2025-06-03 22:43
Last seen: 2025-06-03 22:43