Skip to content

Latest commit

 

History

History
206 lines (155 loc) · 5.13 KB

foodrepo_api.md

File metadata and controls

206 lines (155 loc) · 5.13 KB

The Open Food Repo Logo

OpenFood API version 3

Ruby Example Code

Click any example herein to expand the code.

Product Endpoints

Get Product by ID (Try it!)

Get a product whose ID you know (e.g. `2663`)
# Sample Ruby code for a call against the Food Repo API v3 product by ID

# USAGE:
# $ ruby product.rb

require 'httparty'
require 'json'

BASE_URL='https://www.foodrepo.org/api/v3'
KEY='API_KEY'
ID=2663
ENDPOINT="/products/#{ID}"

url = BASE_URL + ENDPOINT

headers = {
  'Authorization' => "Token token=#{KEY}",
  'Accept' => 'application/json',
  'Content-Type' => 'application/vnd.api+json'
}

response = HTTParty.get(url, headers: headers)
puts "Status: #{response.code}"
if response.code == 200
  puts JSON.parse(response.body)['data']
end

List of Products (Try it!)

Supports query parameters for paging, filtering by barcode, and excluding fields that you may not interested in (such as nutrients or ingredients_translations).

Get page 2 of all products, with 5 products per page
# Sample Ruby code for a call against the Food Repo API v3 products listing

# USAGE:
# $ ruby product_list.rb

require 'httparty'
require 'json'

BASE_URL='https://www.foodrepo.org/api/v3'
KEY='API_KEY'
ENDPOINT='/products'

url = BASE_URL + ENDPOINT

query = {
  'page[number]' => 2,
  'page[size]' => 5
}

headers = {
  'Authorization' => "Token token=#{KEY}",
  'Accept' => 'application/json',
  'Content-Type' => 'application/vnd.api+json'
}

response = HTTParty.get(url, query: query, headers: headers)
puts "Status: #{response.code}"
if response.code == 200
  def page_number(link)
    link&.match(/\?.*page%5Bnumber%5D=(\d+)/)&.[](1) || 'unknown'
  end
  json = JSON.parse(response.body)
  curr_page = page_number(json['links']['self'])
  last_page = page_number(json['links']['last'])
  puts "Page: #{curr_page} / #{last_page}"
  puts 'Barcodes on this page:'
  json['data'].each do |product|
    puts "  #{product['barcode']}"
  end
end
Scrape all products from our database
# Sample Ruby code for multiple calls against the Food Repo API v3 products listing, with paging

require 'httparty'
require 'json'

BASE_URL = 'https://www.foodrepo.org/api/v3'
KEY = YOUR_API_KEY_HERE
ENDPOINT = '/products'
DESTINATION = 'foodrepo_products_snapshot.json'
START_TIME = Time.now

url = BASE_URL + ENDPOINT + '?page%5Bsize%5D=200'

headers = {
  'Authorization' => "Token token=#{KEY}",
  'Accept' => 'application/json',
  'Content-Type' => 'application/vnd.api+json'
}

products = []
num_queries = 0

puts 'Fetching products from FoodRepo API...'

loop do
  response = HTTParty.get(url, headers: headers)
  num_queries += 1
  raise unless response.code == 200 # HTTP OK
  json = JSON.parse(response.body)
  products += json['data']
  print "\rRetrieved products so far: #{products.length}..."
  url = json['links']['next']
  break if url.nil?
end

puts "\n#{products.length} products fetched from #{num_queries} queries."

File.open(DESTINATION, 'w') do |file|
  file << JSON.unparse({
    source: 'foodrepo',
    date: Time.now.utc,
    products: products
  })
end

puts "Data successfully written to: #{DESTINATION}"
puts "Time taken: #{(Time.now - START_TIME).round(1)} seconds"

The above essentially pages through our DB, 200 products at a time, until all products are retrieved, and stores the results into a single json file. Running this code on 2020-06-02 yielded the following output:

Fetching products from FoodRepo API...
Retrieved products so far: 43027...
43027 products fetched from 216 queries.
Data successfully written to: foodrepo_products_snapshot.json
Time taken: 181.4 seconds

Search for Products (Try it!)

Advanced search using ElasticSearch Query DSL in the request data. See the 'Search' section of the main API v3 README for in depth explanations and example queries.

Find some Toblerones
# Sample Ruby code for a call against the Food Repo API v3 product _search

# USAGE:
# $ ruby product_search.rb

require 'httparty'
require 'json'

BASE_URL='https://www.foodrepo.org/api/v3'
KEY='API_KEY'
ENDPOINT='/products/_search'

url = BASE_URL + ENDPOINT

query = <<~JSON
{
  "query": {
    "wildcard": {
      "_all_names" : "*toblerone*"
    }
  }
}
JSON

headers = {
  'Authorization' => "Token token=#{KEY}",
  'Accept' => 'application/json',
  'Content-Type' => 'application/vnd.api+json'
}

response = HTTParty.post(url, headers: headers, body: query)
puts "Status: #{response.code}"
if response.code == 200
  results = JSON.parse(response.body)
  puts "Number of products found: #{results['hits']['total']}"
  puts 'First few products...'
  results['hits']['hits'].each do |hit|
    puts "  #{hit['_source']['display_name_translations']['en']}"
  end
end