Search code examples
ruby-on-railsgraphqlshopifyshopify-appshopify-api

Save GraphQL query from Shopify API in postgres databsae


Question: How to save GraphQL query to my local/postgres database?

(let's assume I just want to save one or two fields -- I'll do more, but I just am not sure how to go about it to begin with.)

Background:

  • I have an embedded shopify app that works with webhooks to consume orders. I run a job, and the data is stored perfectly in my database.

  • I’ve set up a super simple app that makes a graphql query in a model. I’ve set it up so I can see the json object in a view. But am not 100% clear how I go from graphql api query -> response (in model - at least for now) -> save data attributes to my database

  • I am testing this as a new app. So, I am not splitting up models/controllers, etc., just using one model for the moment

  • I guess I am just a bit lost. Do I need to run a job? Or is this something I can do in the controller (or from the model).

Model

shop.rb

class Shop < ActiveRecord::Base
  include ShopifyApp::ShopSessionStorage
  has_many :orders

  def api_version
    ShopifyApp.configuration.api_version
  end

  session = ShopifyAPI::Session.new(domain: "bryanbeshore.myshopify.com", token: Shop.first.shopify_token, api_version: "2020-04")
  ShopifyAPI::Base.activate_session(session)

  client = ShopifyAPI::GraphQL.client

  SHOP_NAME_QUERY = client.parse <<-'GRAPHQL'
      {
    shop {
      name
    }
    orders(first: 100) {
      edges {
        node {
          id
          name
          createdAt
          shippingAddress {
            address1
            address2
            city
            province
            provinceCode
            zip
          }
        }
      }
    }
    }
  GRAPHQL
end

Controller

home_controller.rb

class HomeController < AuthenticatedController

  def index
    client = ShopifyAPI::GraphQL.client
    @shop_orders = client.query(Shop::SHOP_NAME_QUERY).data.to_json
  end
end

View

app/views/home/index.html.erb

<p><%= @shop_orders %></p>

Current Schema

ActiveRecord::Schema.define(version: 2020_05_06_181457) do

  create_table "orders", force: :cascade do |t|
    t.string "shopify_order_id", null: false
    t.string "shopify_order_name", default: ""
    t.datetime "shopify_order_created_at"
    t.integer "shop_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["shop_id"], name: "index_orders_on_shop_id"
    t.index ["shopify_order_id"], name: "index_orders_on_shopify_order_id", unique: true
  end

  create_table "shops", force: :cascade do |t|
    t.string "shopify_domain", null: false
    t.string "shopify_token", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["shopify_domain"], name: "index_shops_on_shopify_domain", unique: true
  end

end


Solution

  • You are querying Shop orders, so I'd create an Order model / orders table, make sure it belongs to a shop.

    • rails g model Order payload:jsonb shop:references, for this example I'm just creating one jsonb field that we will dump the whole JSON object into.
    • rails db:migrate
    • Add belongs_to :shop in models/order.rb
    • Make sure that Shop model has this has_many :orders, usually rails add it for you

    Now, when you get your JSON payload from Shopify, loop through it and create a new record for each order you got.

    So in the method you use to query orders add this.

    shopify_json_response.each do |item|
      orders.create(payload: item)
    end
    

    More or less, that should do the trick. You don't need a background job for this, however background jobs are ideal when you want to process data that doesn't need to be processed right away.