mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Find broader taxon if we don't have a specific one
For example, when importing `beef` products associate the type `meat-product` instead because we don't have a specific beef category.
This commit is contained in:
@@ -1,11 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ProductTypeImporter < DfcBuilder
|
||||
# Try to find the taxon closest matching the given product type.
|
||||
# If we don't find any matching taxon, we return a random one.
|
||||
def self.taxon(product_type)
|
||||
dfc_id = product_type&.semanticId
|
||||
priority_list = [product_type, *list_broaders(product_type)].compact
|
||||
|
||||
# Every product needs a primary taxon to be valid. So if we don't have
|
||||
# one or can't find it we just take a random one.
|
||||
Spree::Taxon.find_by(dfc_id:) || Spree::Taxon.first
|
||||
# Optimistic querying.
|
||||
# We could query all broader taxons in one but then we need to still sort
|
||||
# them locally and use more memory. That would be a pessimistic query.
|
||||
# Consider caching the result instead.
|
||||
taxons = priority_list.lazy.map do |type|
|
||||
Spree::Taxon.find_by(dfc_id: type.semanticId)
|
||||
end.compact
|
||||
|
||||
taxons.first || Spree::Taxon.first
|
||||
end
|
||||
|
||||
def self.list_broaders(type)
|
||||
return [] if type.nil?
|
||||
|
||||
broaders = type.broaders.map do |id|
|
||||
DataFoodConsortium::Connector::SKOSParser.concepts[id]
|
||||
end
|
||||
|
||||
broaders + broaders.flat_map do |broader|
|
||||
list_broaders(broader)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../spec_helper"
|
||||
|
||||
RSpec.describe ProductTypeImporter do
|
||||
let(:drink) {
|
||||
DfcLoader.connector.PRODUCT_TYPES.DRINK
|
||||
}
|
||||
let(:soft_drink) {
|
||||
DfcLoader.connector.PRODUCT_TYPES.DRINK.SOFT_DRINK
|
||||
}
|
||||
let(:lemonade) {
|
||||
DfcLoader.connector.PRODUCT_TYPES.DRINK.SOFT_DRINK.LEMONADE
|
||||
}
|
||||
|
||||
describe ".taxon" do
|
||||
it "finds a linked taxon" do
|
||||
create(:taxon, dfc_id: soft_drink.semanticId)
|
||||
lemonade_taxon = create(:taxon, dfc_id: lemonade.semanticId)
|
||||
expect(described_class.taxon(lemonade)).to eq lemonade_taxon
|
||||
end
|
||||
|
||||
it "falls back to a broader taxon" do
|
||||
drink_taxon = create(:taxon, dfc_id: drink.semanticId)
|
||||
expect(described_class.taxon(lemonade)).to eq drink_taxon
|
||||
end
|
||||
|
||||
it "returns random taxon when none can be found" do
|
||||
only_taxon = create(:taxon)
|
||||
expect(described_class.taxon(lemonade)).to eq only_taxon
|
||||
end
|
||||
|
||||
it "queries the database only until it found a taxon" do
|
||||
soft_drink_taxon = create(:taxon, dfc_id: soft_drink.semanticId)
|
||||
|
||||
expect {
|
||||
expect(described_class.taxon(lemonade)).to eq soft_drink_taxon
|
||||
}.to query_database [
|
||||
"Spree::Taxon Load", # query for lemonade, not found
|
||||
"Spree::Taxon Load", # query for soft drink, found
|
||||
# no query for drink
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe ".list_broaders" do
|
||||
it "returns an empty array if no type is given" do
|
||||
list = described_class.list_broaders(nil)
|
||||
expect(list).to eq []
|
||||
end
|
||||
|
||||
it "can return an empty list for top concepts" do
|
||||
list = described_class.list_broaders(drink)
|
||||
expect(list).to eq []
|
||||
end
|
||||
|
||||
it "lists the broader concepts of a type" do
|
||||
list = described_class.list_broaders(soft_drink)
|
||||
expect(list).to eq [drink]
|
||||
end
|
||||
|
||||
it "lists all the broader concepts to the top concepts" do
|
||||
list = described_class.list_broaders(lemonade)
|
||||
expect(list).to eq [soft_drink, drink]
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user