Reducing the suck with Rails Engines

train engine

Mid last year I worked on adding a feature to the forum software at Shopify because I wanted to have a bit of context before clicking on a link in my emails. Since adding that feature I feel like I've become far more active on our developer forums and have helped answer a number of questions. It's also given me a lot of insight into the kinds of things that make software sucks.

One thing I'd often see are people asking about getting products along with order information. The problem is if an order would come in with 4 line items, they'd need to make another 4 API calls before they could do anything since the line items only contain product IDs. This is pretty shitty, and my response would typically end up being "you'll need to cache that locally and keep it up to date". Then I started thinking about the problem a bit more and realized that I'd be pretty pissed off if someone told me that.

On top of solving the business problem, I now need to do some boring bullshit in order to save on some API calls. Of course, if I want to passively keep the data up to date I need to add Webhook support and now this minor detail has exploded in scope if I want to be able to scale this at all.

Looking into it a bit more I realized that this is a problem that only needs to be solved once (per language/framework). Being a Rails developer and hearing so much about these engines that are all the rage I figured this is the perfect use case for them. The goal is to give Rails developers a drop in module that makes it super easy to get product detail caching working in your projects with little to no effort.

Currently the engine is in a state that with a little bit of code you can get a bunch of products imported into your application. For example, I have a controller with an import action that does the following:

def import
  api_products = ShopifyAPI::Product.find(:all)
  ShopProductSink::Product.create_from_resources(api_products)
  redirect_to root_path
end

And here is accessing that route in action:

Invoking /import for a logged in user

So there's a bit of work still on the developers side that requires a bit of insight and the API is still a little bit in flux. I'm currently not planning on doing any magic (I'm not smart enough for that yet), though I figure once I get it out there and get feedback I'll be able to make it even better.

If you're interested you can keep track of the project on github


One Response
Sorry, but commenting has been disabled.