Small class to simplify the writing and handling of GraphQL queries and mutations for the Shopify Admin API. Comes with built-in retry, pagination, error handling, and more!
It's recommended to organize queries and mutations by subclassing ShopifyAPI::GraphQL::Request:
require "shopify_api/graphql/request"
class ShopifyProduct < ShopifyAPI::GraphQL::Request
# Define your queries/mutations
FIND =<<-GQL
query($id: ID!) {
product(id: $id) {
id
title
descriptionHtml
}
}
GQL
UPDATE =<<-GQL
mutation($product: ProductUpdateInput!) {
productUpdate(product: $product) {
product {
id
title
descriptionHtml
}
userErrors {
field
message
}
}
}
GQL
LIST <<-GQL
query($after: String) {
products(first: 25 after: $after) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
id
title
descriptionHtml
}
}
}
}
GQL
def find(id)
execute(FIND, :id => gid::Product(id)).dig(:data, :product)
end
def update(id, changes)
execute(UPDATE, :product => changes.merge(:id => gid::Product(id))).dig(:data, :product_update, :product)
end
def list
paginate(LIST) { |page| yield page.dig(:data, :products, :edges) }
end
endThen use it:
shopify = ShopifyProduct.new("a-shop", token)
begin
product = shopify.find(123)
p product[:id]
p product[:description_html]
rescue ShopifyAPI::GraphQL::Request::NotFoundError => e
warn "Product not found: #{e}"
end
begin
product = shopify.update(123, :description_html => "Something amaaaazing!")
p product[:id]
p product[:description_html]
rescue ShopifyAPI::GraphQL::Request::UserError => e
warn "User errors:"
e.errors { |err| warn err["field"] }
end
begin
shopify.list(123) do |node|
product = node[:node]
p product[:id]
p product[:description_html]
end
rescue ShopifyAPI::GraphQL::Request::NotFoundError => e
warn "Request failed: #{e}"
endSubclasses have access to the following methods:
#execute- Execute a query or mutation with the provided arguments#paginate- Execute a query with pagination; without a block a lazy enumerator (Enumerator::Lazy) is returned#gid- Used for Global ID manipulation (an instance ofTinyGID)#gql- The underlying GraphQL client (an instance ofShopifyAPI::GraphQL::Tiny)
#execute and #paginate also:
- Automatically retry failed or rate-limited requests
- Accept
snake_caseSymbolkeys - Return a
Hashwithsnake_caseSymbolkeys - Raise a
UserErrorwhen a mutation's response containsuserErrors - Raise a
NotFoundErrorwhen a query's result cannot be found
Both of these are small wrappers around the equivalent methods on ShopifyAPI::GraphQL::Tiny.
For more information see its documentation on retries.
With the exception of retry, most defaults can be disabled per instance or per execution:
class ShopifyProduct < ShopifyAPI::GraphQL::Request
def initialize(shop, token)
super(shop, token, :raise_if_not_found => false, :raise_if_user_errors => false, :snake_case => false)
end
def find(gid)
execute(QUERY, :raise_if_not_found => true)
end
endDisabling retry must be done per instance.
Pass the desired version to Request's constructor:
class ShopifyProduct < ShopifyAPI::GraphQL::Request
def initialize(shop, token)
super(shop, token, :version => "2026-01")
end
endOf course you can make requests directly on an instance of ShopifyAPI::GraphQL::Request:
require "shopify_api/graphql/request"
request = ShopifyAPI::GraphQL::Request.new("a-shop", token)
begin
product = request.execute(query, :id => "gid://shopify/Product/123").dig(:data, :product)
p product[:title]
p product[:description_html]
rescue ShopifyAPI::GraphQL::Request::NotFoundError => e
p e
endAnd mutations:
begin
product = request.execute(mutation, :id => "gid://shopify/Product/123", :title => "Foo Hoo!").dig(:data, :product)
rescue ShopifyAPI::GraphQL::Request::UserError => e
p e
endFor more information checkout the API docs
- Easy-to-use
- Built-in retry
- Built-in pagination
- Improved exception handling
- You can use
:snake_casehash keys - Lightweight
Overall, Shopify's API client is bloated trash that will give you development headaches and long-term maintenance nightmares.
We used to use it, staring way back in 2015, but eventually had to pivot away from their Ruby libraries due to developer frustration and high maintenance cost (and don't get us started on the ShopifyApp gem!@#).
For more information see: Shopify/shopify-api-ruby#1181
cp env.template .env and fill-in .env with the missing values. This requires a Shopify store.
- Shopify Dev Tools - Command-line program to assist with the development and/or maintenance of Shopify apps and stores
- Shopify ID Export - Dump Shopify product and variant IDs —along with other identifiers— to a CSV or JSON file
ShopifyAPI::GraphQL::Tiny- Lightweight, no-nonsense, Shopify GraphQL Admin API client with built-in pagination and retryTinyGID- Build Global ID (gid://) URI strings from scalar values
The gem is available as open source under the terms of the MIT License.
Made by ScreenStaring