Skip to content

Commit

Permalink
Add validation of metadata on record save
Browse files Browse the repository at this point in the history
  • Loading branch information
RobNicholsGDS committed Nov 21, 2024
1 parent aa6145d commit a8de821
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 4 deletions.
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ gem "faraday"
gem "oj" # JSON parser
gem "rabl"

# JSON Schema Validation
gem "json-schema"

group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[mri windows], require: "debug/prelude"
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ GEM
jsbundling-rails (1.3.1)
railties (>= 6.0.0)
json (2.8.2)
json-schema (5.1.0)
addressable (~> 2.8)
kamal (2.3.0)
activesupport (>= 7.0)
base64 (~> 0.2)
Expand Down Expand Up @@ -435,6 +437,7 @@ DEPENDENCIES
govuk-components
govuk_design_system_formbuilder
jsbundling-rails
json-schema
kamal
oj
pg (~> 1.1)
Expand Down
8 changes: 8 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
module ApplicationHelper
def valid_record_tag(record)
text, colour = if record.json_valid?
%w[Valid green]
else
%w[Invalid red]
end
content_tag :strong, text, class: "govuk-tag govuk-tag--#{colour}"
end
end
6 changes: 5 additions & 1 deletion app/models/record.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class Record < ApplicationRecord
before_validation :json_parse_metadata
before_validation :json_parse_metadata, :store_metadata_validation

validates :name, :metadata, presence: true

Expand All @@ -11,4 +11,8 @@ def json_parse_metadata
rescue JSON::ParserError => e
errors.add :metadata, e.message
end

def store_metadata_validation
self.json_valid = JsonValidator.valid?(metadata)
end
end
17 changes: 17 additions & 0 deletions app/services/json_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class JsonValidator
JSON_SCHEMA_PATH = "https://co-cddo.github.io/data-catalogue-metadata/schema/dataset_schema.json".freeze

def self.valid?(json)
new(json).valid?
end

attr_reader :json

def initialize(json)
@json = json
end

def valid?
JSON::Validator.validate JSON_SCHEMA_PATH, json
end
end
2 changes: 1 addition & 1 deletion app/views/records/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<%= record.name %>
</td>
<td class="govuk-table__cell">
<%#= valid_record_tag(record) %>
<%= valid_record_tag(record) %>
</td>
<td class="govuk-table__cell">
<%= link_to "Show this record", record %>
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20241121094103_add_json_valid_to_records.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddJsonValidToRecords < ActiveRecord::Migration[8.0]
def change
add_column :records, :json_valid, :boolean
end
end
3 changes: 2 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions spec/fixtures/files/dataset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"identifier": "8d085327-21b6-4d8b-9705-88faad231d22",
"supplierIdentifier": "acme-123",
"modified": "2023-12-09T16:09:53+00:00",
"status": "Published",
"title": "Advance Passenger Information",
"description": "Travel data and personal data given to airlines by passenger. API covers both inbound and outbound air passengers. API includes the passenger’s full name, nationality, date of birth, gender and travel document number, type and country of issue.The data does not include those arriving by sea or rail routes, by private aircraft or via the Common Travel Area (CTA).",
"type": "Data Set",
"theme": [
"Transport and infrastructure",
"Population and society"
],
"keyword": [
"Air travel",
"Passport",
"Airports",
"leaving UK",
"entering UK"
],
"contactPoint": [
{
"name": "Rob Nichols",
"email": "[email protected]"
}
],
"publisher": "academy-for-social-justice",
"securityClassification": "OFFICIAL",
"accessRights": "INTERNAL",
"distribution": [
{
"accessService": ["8d085327-21b6-4d8b-9705-88faad231d23"],
"downloadURL": "http://example.com/path/to/file.csv",
"mediaType":["text/csv"]
}
]
}
17 changes: 16 additions & 1 deletion spec/models/record_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
require "rails_helper"

RSpec.describe Record, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
describe "metadata validated on save" do
let(:record) { create :record, metadata: { invalid: :content } }

it "sets json_valid as false if metadata doesn't match schema" do
expect(record.json_valid).to be_falsey
end

context "with valid data" do
let(:metadata) { json_from_fixture("dataset.json") }
let(:record) { create :record, metadata: }

it "sets json_valid as true" do
expect(record.json_valid).to be_truthy
end
end
end
end
19 changes: 19 additions & 0 deletions spec/services/json_validator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require "rails_helper"

RSpec.describe JsonValidator, type: :service do
describe ".valid?" do
let(:json) { json_from_fixture("dataset.json") }

it "is true for valid json" do
expect(described_class.valid?(json)).to be_truthy
end

context "with invalid json" do
let(:json) { { invalid: :content }.to_json }

it "is false" do
expect(described_class.valid?(json)).not_to be_truthy
end
end
end
end
3 changes: 3 additions & 0 deletions spec/support/fixture_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def json_from_fixture(path)
JSON.parse(File.read(fixture_file_upload(path)))
end
3 changes: 3 additions & 0 deletions spec/support/webmock.rb
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
require "webmock/rspec"

# Allow calls to JSON schema
WebMock.disable_net_connect!(allow: "https://co-cddo.github.io")

0 comments on commit a8de821

Please sign in to comment.