如何使用Ruby on Rails为Shopify嵌入式应用实现订单分页?
Hey there! Since you're a Ruby newbie working on a Shopify embedded app with Sinatra and want to avoid loading all orders at once (smart move—no one wants slow load times!), let's walk through how to implement backend-side pagination step by step. This way, you only fetch the orders you need for each page.
Step 1: Use Shopify API's Pagination Parameters
Shopify's Order API supports basic pagination with limit (max 250 orders per page) and page parameters. This is perfect for beginners because it's straightforward to implement.
Step 2: Update Your Sinatra Route to Handle Pagination
First, make sure you're using the shopify_api gem (you should have this set up from the tutorial). Here's how to modify your route to fetch only the orders for the current page, plus calculate total pages for navigation:
# In your Sinatra app file (like app.rb) get '/orders' do # Get the current page from the request, default to 1 if not provided current_page = params[:page] ? params[:page].to_i : 1 # Set how many orders to show per page (adjust this as needed, max 250) orders_per_page = 50 # Fetch the orders for the current page using Shopify API orders = ShopifyAPI::Order.find( :all, params: { limit: orders_per_page, page: current_page } ) # Get total number of orders to calculate total pages total_orders = ShopifyAPI::Order.count total_pages = (total_orders.to_f / orders_per_page).ceil # Pass data to your ERB template erb :orders, locals: { orders: orders, current_page: current_page, total_pages: total_pages, orders_per_page: orders_per_page } end
Step 3: Build the Frontend Table & Pagination Controls
Now update your orders.erb template to render the order table and add pagination buttons. We'll include logic to disable "Previous" on the first page and "Next" on the last page:
<!-- orders.erb --> <h2>Your Orders</h2> <!-- Order Table --> <table style="width:100%; border-collapse: collapse;"> <thead> <tr style="background: #f0f0f0;"> <th style="border: 1px solid #ddd; padding: 8px;">Order Number</th> <th style="border: 1px solid #ddd; padding: 8px;">Customer</th> <th style="border: 1px solid #ddd; padding: 8px;">Total</th> <th style="border: 1px solid #ddd; padding: 8px;">Date</th> </tr> </thead> <tbody> <% orders.each do |order| %> <tr> <td style="border: 1px solid #ddd; padding: 8px;"><%= order.name %></td> <td style="border: 1px solid #ddd; padding: 8px;"> <%= order.customer ? "#{order.customer.first_name} #{order.customer.last_name}" : "Guest" %> </td> <td style="border: 1px solid #ddd; padding: 8px;"><%= order.total_price %></td> <td style="border: 1px solid #ddd; padding: 8px;"><%= order.created_at.strftime("%Y-%m-%d %H:%M") %></td> </tr> <% end %> </tbody> </table> <!-- Pagination Navigation --> <div style="margin-top: 20px; text-align: center;"> <!-- Previous Button --> <% if current_page > 1 %> <a href="/orders?page=<%= current_page - 1 %>" style="padding: 8px 12px; margin: 0 4px; border: 1px solid #ddd; text-decoration: none; color: #000;">Previous</a> <% else %> <span style="padding: 8px 12px; margin: 0 4px; border: 1px solid #ddd; color: #ccc;">Previous</span> <% end %> <!-- Page Numbers --> <% (1..total_pages).each do |page_num| %> <% if page_num == current_page %> <span style="padding: 8px 12px; margin: 0 4px; background: #008060; color: white; border: 1px solid #008060;"><%= page_num %></span> <% else %> <a href="/orders?page=<%= page_num %>" style="padding: 8px 12px; margin: 0 4px; border: 1px solid #ddd; text-decoration: none; color: #000;"><%= page_num %></a> <% end %> <% end %> <!-- Next Button --> <% if current_page < total_pages %> <a href="/orders?page=<%= current_page + 1 %>" style="padding: 8px 12px; margin: 0 4px; border: 1px solid #ddd; text-decoration: none; color: #000;">Next</a> <% else %> <span style="padding: 8px 12px; margin: 0 4px; border: 1px solid #ddd; color: #ccc;">Next</span> <% end %> </div>
Bonus: Advanced Cursor-Based Pagination (For Larger Datasets)
If you expect thousands of orders, Shopify recommends using cursor-based pagination instead of page (since page can skip or duplicate orders if data changes between requests). Here's a quick overview:
When you fetch orders, the Shopify API returns a Link header with URLs for the next/previous pages. You can parse this header to get the page_info cursor, then use it in your next request:
# Fetch first page response = ShopifyAPI::Order.find(:all, params: { limit: orders_per_page }, headers: { 'Accept' => 'application/json' }) # Parse Link header to get next page cursor (you'll need to write a helper to extract this) next_page_cursor = extract_next_page_cursor(response.headers['Link']) # Fetch next page using cursor next_orders = ShopifyAPI::Order.find(:all, params: { limit: orders_per_page, page_info: next_page_cursor })
This is more robust, but for a beginner, starting with page and limit is totally fine—you can upgrade later if needed!
Quick Notes
- Make sure your route is protected by Shopify's authentication middleware (from the tutorial) so only authorized users can access orders.
- Adjust
orders_per_pageto fit your needs (max 250, per Shopify's API limits).
That should do it! Now your app will only load one page of orders at a time, keeping things fast and efficient.
内容的提问来源于stack exchange,提问作者Nicole

