Use ActiveModelSerializer for DFC serialization

This commit is contained in:
François Turbelin
2020-08-12 12:24:31 +02:00
parent 8687e0199d
commit 2a8268ca73
10 changed files with 182 additions and 108 deletions

View File

@@ -64,6 +64,7 @@ PATH
remote: engines/dfc_provider
specs:
dfc_provider (0.0.1)
active_model_serializers (~> 0.8.4)
jwt (~> 2.2)
rspec (~> 3.9)

View File

@@ -14,7 +14,10 @@ module DfcProvider
respond_to :json
def index
render json: serialized_data_for(@user)
render json: @user,
serializer: DfcProvider::PersonSerializer,
meta: meta_data,
meta_key: '@context'
end
private
@@ -54,14 +57,11 @@ module DfcProvider
DfcProvider::AuthorizationControl.new(access_token)
end
def serialized_data_for(user)
def meta_data
{
"@context" =>
{
"dfc" => "http://datafoodconsortium.org/ontologies/DFC_FullModel.owl#",
"@base" => "#{root_url}api/dfc_provider"
}
}.merge(DfcProvider::PersonSerializer.new(user).serialized_data)
"dfc" => "http://datafoodconsortium.org/ontologies/DFC_FullModel.owl#",
"@base" => "#{root_url}api/dfc_provider"
}
end
end
end

View File

@@ -0,0 +1,22 @@
# frozen_string_literal: true
# Serializer used to render the DFC Address from an OFN User
# into JSON-LD format based on DFC ontology
module DfcProvider
class AddressSerializer < ActiveModel::Serializer
attribute :type, key: '@type'
attribute :city, key: 'dfc:city'
attribute :country, key: 'dfc:country'
attribute :postcode, key: 'dfc:postcode'
attribute :street, key: 'dfc:street'
def type
'dfc:Address'
end
def city; end
def country; end
def postcode; end
def street; end
end
end

View File

@@ -3,31 +3,39 @@
# Serializer used to render a DFC CatalogItem from an OFN Product
# into JSON-LD format based on DFC ontology
module DfcProvider
class CatalogItemSerializer
def initialize(variant)
@variant = variant
class CatalogItemSerializer < ActiveModel::Serializer
attribute :id, key: '@id'
attribute :type, key: '@type'
attribute :references, key: 'dfc:references'
attribute :sku, key: 'dfc:sku'
attribute :stock_limitation, key: 'dfc:stockLimitation'
has_many :offered_through,
serializer: DfcProvider::OfferSerializer,
key: 'dfc:offeredThrough'
def id
"/catalog_items/#{object.id}"
end
def serialized_data
def type
'dfc:CatalogItem'
end
def references
{
"@id" => "/catalog_items/#{@variant.id}",
"@type" => "dfc:CatalogItem",
"dfc:references" => {
"@type" => "@id",
"@id" => "/supplied_products/#{@variant.product_id}"
},
"dfc:sku" => @variant.sku,
"dfc:stockLimitation" => nil,
"dfc:offeredThrough" => serialized_offers
'@type' => '@id',
'@id' => "/supplied_products/#{object.product_id}"
}
end
private
def sku
object.sku
end
def serialized_offers
[
OfferSerializer.new(@variant).serialized_data
]
def stock_limitation; end
def offered_through
[object]
end
end
end

View File

@@ -3,43 +3,47 @@
# Serializer used to render a DFC Enterprise from an OFN Enterprise
# into JSON-LD format based on DFC ontology
module DfcProvider
class EnterpriseSerializer
def initialize(enterprise)
@enterprise = enterprise
class EnterpriseSerializer < ActiveModel::Serializer
attribute :id, key: '@id'
attribute :type, key: '@type'
attribute :vat_number, key: 'dfc:VATnumber'
has_many :defines, key: 'dfc:defines'
has_many :supplies,
key: 'dfc:supplies',
serializer: DfcProvider::SuppliedProductSerializer
has_many :manages,
key: 'dfc:manages',
serializer: DfcProvider::CatalogItemSerializer
def id
"/entreprises/#{object.id}"
end
def serialized_data
{
"@id" => "/entreprises/#{@enterprise.id}",
"@type" => "dfc:Entreprise",
"dfc:VATnumber" => nil,
"dfc:defines" => [],
"dfc:supplies" => serialized_supplied_products,
"dfc:manages" => serialized_catalog_items
}
def type
'dfc:Entreprise'
end
def vat_number; end
def defines
[]
end
def supplies
products
end
def manages
products.map(&:variants).flatten
end
private
def products
@products ||=
@enterprise.
object.
supplied_products.
includes(variants: :product)
end
def serialized_supplied_products
products.map do |product|
SuppliedProductSerializer.new(product).serialized_data
end
end
def serialized_catalog_items
@products.map do |product|
product.variants.map do |variant|
CatalogItemSerializer.new(variant).serialized_data
end
end.flatten
end
end
end

View File

@@ -3,22 +3,34 @@
# Serializer used to render the DFC Offer from an OFN Product
# into JSON-LD format based on DFC ontology
module DfcProvider
class OfferSerializer
def initialize(variant)
@variant = variant
class OfferSerializer < ActiveModel::Serializer
attribute :id, key: '@id'
attribute :type, key: '@type'
attribute :offeres_to, key: 'dfc:offeres_to'
attribute :price, key: 'dfc:price'
attribute :stock_limitation, key: 'dfc:stockLimitation'
def id
"/offers/#{object.id}"
end
def serialized_data
def type
'dfc:Offer'
end
def offeres_to
{
"@id" => "offers/#{@variant.id}",
"@type" => "dfc:Offer",
"dfc:offeresTo" => {
"@type" => "@id",
"@id" => "/customerCategoryId1"
},
"dfc:price" => @variant.price,
"dfc:stockLimitation" => @variant.on_hand,
'@type' => '@id',
'@id' => nil
}
end
def price
object.price
end
def stock_limitation
object.on_hand
end
end
end

View File

@@ -3,34 +3,34 @@
# Serializer used to render the DFC Person from an OFN User
# into JSON-LD format based on DFC ontology
module DfcProvider
class PersonSerializer
def initialize(user)
@user = user
class PersonSerializer < ActiveModel::Serializer
attribute :id, key: '@id'
attribute :type, key: '@type'
attribute :family_name, key: 'dfc:familyName'
attribute :first_name, key: 'dfc:firstName'
has_one :address,
key: 'dfc:hasAddress',
serializer: DfcProvider::AddressSerializer
has_many :affiliates,
key: 'dfc:affiliates',
serializer: DfcProvider::EnterpriseSerializer
def id
"/personId/#{object.id}"
end
def serialized_data
{
"@id" => "/personId/#{@user.id}",
"@type" => "dfc:Person",
"dfc:familyName" => @user.login,
"dfc:firtsName" => @user.email,
"dfc:hasAdress" => {
"@type" => "dfc:Address",
"dfc:city" => nil,
"dfc:country" => nil,
"dfc:postcode" => nil,
"dfc:street" => nil
},
"dfc:affiliates" => affiliates_serialized_data
}
def type
'dfc:Person'
end
private
def family_name; end
def affiliates_serialized_data
@user.enterprises.map do |enterprise|
EnterpriseSerializer.new(enterprise).serialized_data
end
def first_name; end
def address; end
def affiliates
object.enterprises
end
end
end

View File

@@ -3,33 +3,59 @@
# Serializer used to render a DFC SuppliedProduct from an OFN Product
# into JSON-LD format based on DFC ontology
module DfcProvider
class SuppliedProductSerializer
def initialize(product)
@product = product
class SuppliedProductSerializer < ActiveModel::Serializer
attribute :id, key: '@id'
attribute :type, key: '@type'
attribute :unit, key: 'dfc:hasUnit'
attribute :quantity, key: 'dfc:quantity'
attribute :description, key: 'dfc:description'
attribute :total_theoritical_stock, key: 'dfc:totalTheoriticalStock'
attribute :brand, key: 'dfc:brand'
attribute :claim, key: 'dfc:claim'
attribute :image, key: 'dfc:image'
attribute :life_time, key: 'lifeTime'
has_many :physical_characteristics, key: 'dfc:physicalCharacterisctics'
def id
"/supplied_products/#{object.id}"
end
def serialized_data
def type
'dfc:SuppliedProduct'
end
def unit
{
"@id" => "/products/#{@product.id}",
"dfc:hasUnit" => {
"@id" => "/unit/#{unit_name}",
"rdfs:label" => unit_name
},
"dfc:quantity" => @product.on_hand,
"dfc:description" => @product.name,
"dfc:totalTheoriticalStock" => nil,
"dfc:brand" => nil,
"dfc:claim" => nil,
"dfc:image" => @product.images.first.try(:attachment, :url),
"lifeTime" => nil,
"dfc:physicalCharacterisctics" => nil
'@id' => "/unit/#{unit_name}",
'rdfs:label' => unit_name
}
end
def quantity
object.on_hand
end
def description
object.name
end
def total_theoritical_stock; end
def brand; end
def claim; end
def image
object.images.first.try(:attachment, :url)
end
def life_time; end
def physical_characteristics
[]
end
private
def unit_name
@product.unit_description.presence || 'piece'
object.unit_description.presence || 'piece'
end
end
end

View File

@@ -18,4 +18,5 @@ Gem::Specification.new do |spec|
spec.add_dependency 'jwt', '~> 2.2'
spec.add_dependency 'rspec', '~> 3.9'
spec.add_dependency 'active_model_serializers', '~> 0.8.4'
end

View File

@@ -35,7 +35,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do
expect(response.body)
.to include(product.name)
expect(response.body)
.to include(user.email)
.to include(product.sku)
expect(response.body)
.to include("offers/#{product.variants.first.id}")
end
@@ -62,7 +62,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do
expect(response.body)
.to include(product.name)
expect(response.body)
.to include(user.email)
.to include(product.sku)
expect(response.body)
.to include("offers/#{product.variants.first.id}")
end