Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP GobiertoData add dcat catalog endpoint #3846

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
8 changes: 8 additions & 0 deletions app/controllers/gobierto_data/api/v1/datasets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ class DatasetsController < BaseController
skip_before_action :authenticate_in_site, only: [:new, :create, :update, :destroy]
skip_before_action :set_admin_with_token, except: [:new, :create, :update, :destroy]

# GET /api/v1/data/catalog.xml
def catalog
@catalog = DatasetPresenter.new(current_site).build_catalog
respond_to do |format|
format.xml
end
stbnrivas marked this conversation as resolved.
Show resolved Hide resolved
end

# GET /api/v1/data/datasets
# GET /api/v1/data/datasets.json
# GET /api/v1/data/datasets.csv
Expand Down
3 changes: 3 additions & 0 deletions app/models/gobierto_data/dataset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ class Dataset < ApplicationRecord
include GobiertoData::Favoriteable
include GobiertoAttachments::Attachable
include GobiertoCommon::Collectionable
include GobiertoCommon::HasCustomFieldRecords

belongs_to :site
has_many :queries, dependent: :destroy, class_name: "GobiertoData::Query"
has_many :visualizations, dependent: :destroy, class_name: "GobiertoData::Visualization"

scope :sorted, -> { order(data_updated_at: :desc) }
scope :visibles, -> { where(visibility_level: "active") }
scope :by_site, ->(site_id) { where(site_id: site_id) }
ferblape marked this conversation as resolved.
Show resolved Hide resolved

translates :name

Expand Down
76 changes: 76 additions & 0 deletions app/presenters/gobierto_data/dataset_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
module GobiertoData
class DatasetPresenter
include ActionView::Helpers::UrlHelper

attr_reader :site

def initialize(site)
@site = site
end

def build_catalog
catalog = {
identifier_uri: url_helpers.gobierto_data_root_url(host: site.domain),
title: "dcat catalog for #{site}",
description: "this is catalog published by #{@catalog_identifier_uri} which contains datasets",
ferblape marked this conversation as resolved.
Show resolved Hide resolved
issued: site.created_at,
modified: GobiertoData::Dataset.where(site_id: site.id).maximum(:created_at) || site.created_at,
ferblape marked this conversation as resolved.
Show resolved Hide resolved
languages: site["configuration_data"]["available_locales"],
ferblape marked this conversation as resolved.
Show resolved Hide resolved
homepage: url_helpers.gobierto_data_root_url(host: site.domain),
license_url: "https://opendatacommons.org/licenses/odbl/",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alvaro said no license, right? Is it mandatory?

Copy link
Contributor Author

@stbnrivas stbnrivas Apr 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about if DCAT has mandatory xml elements, from now I think that:

  • DCAT don't define xml element required, recommended, optional.
  • DCAT-AP define some xml element as required, reccomended or optionals (but not 100% sure)

So as alvaro said I'll remove license at catalog level 👍

datasets: build_datasets_for_catalog
}
end

private

def build_datasets_for_catalog
datasets = []
Dataset.where(site_id: site.id).visibles.each do |dataset|
datasets << build_dataset_for_catalog(dataset)
end
datasets
stbnrivas marked this conversation as resolved.
Show resolved Hide resolved
end

def build_dataset_for_catalog(dataset)
{
url: url_helpers.gobierto_data_datasets_url(host: site.domain, id: dataset.slug),
title: dataset.name,
description: description_custom_field_record(dataset),
keywords: [],
issued: dataset.created_at,
modified: dataset.updated_at,
languages: [site_locale],
license_url: "https://opendatacommons.org/licenses/odbl/",
ferblape marked this conversation as resolved.
Show resolved Hide resolved
publisher: site.name,
publisher_mbox: site.reply_to_email,
distributions: build_distribution_for_catalog(dataset)
}
end

def build_distribution_for_catalog(dataset)
[
{
format: 'application/csv',
download_url: url_helpers.download_gobierto_data_api_v1_dataset_url(dataset, host: site.domain)
}
]
end

def url_helpers
Rails.application.routes.url_helpers
end

def site_locale
site.configuration_data["default_locale"]
ferblape marked this conversation as resolved.
Show resolved Hide resolved
end

def description_custom_field_record(dataset)
if dataset.custom_field_record_with_uid("description")
dataset.custom_field_record_with_uid("description").payload["description"][site_locale]
else
""
end
end
end
end
50 changes: 50 additions & 0 deletions app/views/gobierto_data/api/v1/datasets/catalog.xml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF
xmlns:time="http://www.w3.org/2006/time#"
xmlns:dct="http://purl.org/dc/terms/"
xmlns:dcat="http://www.w3.org/ns/dcat#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><% cache @catalog do %>
<dcat:Catalog rdf:about="https://data.some.org/catalog">
<dct:identifier><%= @catalog[:identifier_uri] %></dct:identifier>
<dct:title><%= @catalog[:title] %></dct:title>
<dct:description><%= @catalog[:description] %></dct:description>
<dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime"><%= @catalog[:issued] %></dct:issued>
<dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime"><%= @catalog[:modified] %></dct:modified>
<%= @catalog[:languages].map { |locale| "<dct:language>#{locale}</dct:language>" }.join.html_safe %>
<foaf:homepage rdf:resource="<%= @catalog[:homepage] %>"/>
<dct:license rdf:resource="<%= @catalog[:license_url] %>"/>
<% @catalog[:datasets].each do |dataset| %><dcat:dataset>
ferblape marked this conversation as resolved.
Show resolved Hide resolved
<dcat:Dataset rdf:about="<%= dataset[:url]%>">
<dct:identifier><%= dataset[:url] %></dct:identifier>
<dct:title><%= dataset[:title] %></dct:title>
<dct:description><%= dataset[:description] %></dct:description>
<%= dataset[:keywords].map { |keyword| "<dct:keyword>#{locale}</dct:keyword>" }.join.html_safe %>
<dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime"><%= dataset[:issued] %></dct:issued>
<dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime"><%= dataset[:modified] %></dct:modified>
<%= dataset[:languages].map { |lang| "<dct:language>#{lang}</dct:language>" }.join.html_safe %>
<dct:license rdf:resource="<%= dataset[:title] %>"/>
<dct:publisher>
<foaf:Organization>
<foaf:name><%= dataset[:publisher] %></foaf:name>
<foaf:mbox><%= dataset[:publisher_mbox] %></foaf:mbox>
</foaf:Organization>
</dct:publisher>
<% dataset[:distributions].each do |distribution| %>
<dcat:distribution>
<dcat:Distribution>
<dct:identifier><%= @identifier_uri %></dct:identifier>
<dct:title><%= dataset[:title] %> in CSV format</dct:title>
ferblape marked this conversation as resolved.
Show resolved Hide resolved
<dct:description><%= dataset[:description] %></dct:description>
<dcat:downloadURL rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI"><%= distribution[:download_url] %></dcat:downloadURL>
<dcat:mediaType><%= distribution[:format] %></dcat:mediaType>
<dct:license rdf:resource="<%= dataset[:license_url] %>"/>
</dcat:Distribution>
</dcat:distribution>
<% end %>
</dcat:Dataset>
</dcat:dataset><% end %>
ferblape marked this conversation as resolved.
Show resolved Hide resolved
</dcat:Catalog><% end %>
</rdf:RDF>
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@
resource :favorite, only: [:create, :destroy]
resources :favorites, only: [:index]
end
get "catalog" => "datasets#catalog"
ferblape marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/gobierto_common/custom_field_records.yml
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,11 @@ users_dataset_md_with_translations_custom_field_record:
"md-with-translations" => { en: "Paragraph with translations!", es: "¡Párrafo con traducciones!" }
}.to_json %>

users_dataset_md_with_translations_custom_field_record:
ferblape marked this conversation as resolved.
Show resolved Hide resolved
item: users_dataset (GobiertoData::Dataset)
custom_field: madrid_data_datasets_custom_field_description
payload: <%= {"description": {"en": "This dataset contains the council' persons related.", "es": "Este dataset contiene las personas relaccionadas con el ayuntamiento."}}.to_json %>

## Users

peter_custom_field_issue:
Expand Down
8 changes: 8 additions & 0 deletions test/fixtures/gobierto_common/custom_fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,14 @@ madrid_data_datasets_custom_field_md_with_translations:
field_type: <%= GobiertoCommon::CustomField.field_types[:localized_paragraph] %>
uid: md-with-translations

madrid_data_datasets_custom_field_description:
site: madrid
class_name: GobiertoData::Dataset
position: 4
name_translations: <%= {"en": "Description", "es": "Descripción"}.to_json %>
field_type: <%= GobiertoCommon::CustomField.field_types[:localized_paragraph] %>
uid: description
ferblape marked this conversation as resolved.
Show resolved Hide resolved

madrid_custom_field_human_resources_table_plugin:
site: madrid
class_name: GobiertoPlans::Node
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/sites.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ madrid:
organization_address: Fake St., 123
organization_document_number: 0123456789A
visibility_level: <%= Site.visibility_levels["active"] %>
created_at: <%= 1.year.ago %>
updated_at: <%= 1.week.ago %>

santander:
title_translations: <%= { 'en' => 'Transparencia Ciudadana', 'es' => 'Transparencia Ciudadana' }.to_json %>
Expand Down
57 changes: 57 additions & 0 deletions test/presenters/gobierto_data/dataset_presenter_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

require "test_helper"

module GobiertoData
class DatasetPresenterTest < ActiveSupport::TestCase

def setup
super
@site = sites(:madrid)
@subject = DatasetPresenter.new(@site)
@other_site = sites(:huesca)
@other_subject = DatasetPresenter.new(@other_site)
end

def test_structure_catalog_building_do_not_show_draft_datasets
catalog = @subject.build_catalog
datasets_published = GobiertoData::Dataset.by_site(@site.id).visibles.size
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current_site.datasets?

assert_equal datasets_published, catalog[:datasets].size
end

def test_structure_catalog_building_using_site_with_datasets
catalog = @subject.build_catalog
assert catalog.has_key? :identifier_uri
assert catalog.has_key? :title
assert catalog.has_key? :description
assert catalog.has_key? :issued
assert catalog.has_key? :modified
assert catalog.has_key? :languages
assert catalog.has_key? :homepage
assert catalog.has_key? :license_url
assert catalog.has_key? :datasets
catalog[:datasets].each do |dataset|
assert dataset.has_key? :url
assert dataset.has_key? :title
assert dataset.has_key? :description
assert dataset.has_key? :keywords
assert dataset.has_key? :issued
assert dataset.has_key? :modified
assert dataset.has_key? :languages
assert dataset.has_key? :license_url
assert dataset.has_key? :publisher
assert dataset.has_key? :publisher_mbox
assert dataset.has_key? :distributions
dataset[:distributions].each do |distribution|
assert distribution.has_key? :format
assert distribution.has_key? :download_url
end
end
end

def test_structure_catalog_building_using_site_without_datasets
catalog = @other_subject.build_catalog
assert_equal 0, catalog[:datasets].size
end
end
end