Skip to content

Commit 965b75f

Browse files
authored
Adding Research Outputs (DB and model components only) (#2739)
* sym linked necessary files and ignored others * add research_outputs and mime_types * add new mime_types Rake task to upgrade task * reverted sym links * reverted gitignore changes * reverted blank lines added to bottom of a few configs * reverted issue with open_aire config * minor text change to comment in open_aire initializer to force rubocop fix * Remove blank line added to open_aire initializer by Atom to fix rubocop * add research_outputs and mime_types add new mime_types Rake task to upgrade task reverted sym links reverted gitignore changes reverted blank lines added to bottom of a few configs reverted issue with open_aire config minor text change to comment in open_aire initializer to force rubocop fix Remove blank line added to open_aire initializer by Atom to fix rubocop * updated schema date in schema.rb * removed dupplicate copy of open_aire initializer
1 parent 05acc13 commit 965b75f

File tree

13 files changed

+565
-9
lines changed

13 files changed

+565
-9
lines changed

app/models/mime_type.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# frozen_string_literal: true
2+
3+
# == Schema Information
4+
#
5+
# Table name: mime_types
6+
#
7+
# id :bigint not null, primary key
8+
# category :string not null
9+
# description :string not null
10+
# value :string not null
11+
# created_at :datetime not null
12+
# updated_at :datetime not null
13+
#
14+
# Indexes
15+
#
16+
# index_mime_types_on_value (value)
17+
#
18+
class MimeType < ApplicationRecord
19+
20+
include ValidationMessages
21+
22+
# ================
23+
# = Associations =
24+
# ================
25+
26+
has_many :research_outputs
27+
28+
# ===============
29+
# = Validations =
30+
# ===============
31+
32+
validates :category, :description, :value, presence: { message: PRESENCE_MESSAGE }
33+
34+
# ==========
35+
# = Scopes =
36+
# ==========
37+
38+
# Retrieves the unique list of categories
39+
scope :categories, -> { pluck(:category).uniq.sort { |a, b| a <=> b } }
40+
41+
end

app/models/research_output.rb

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# frozen_string_literal: true
2+
3+
# == Schema Information
4+
#
5+
# Table name: research_outputs
6+
#
7+
# id :bigint not null, primary key
8+
# abbreviation :string
9+
# access :integer default(0), not null
10+
# byte_size :bigint
11+
# coverage_end :datetime
12+
# coverage_region :string
13+
# coverage_start :datetime
14+
# description :text
15+
# display_order :integer
16+
# is_default :boolean default("false")
17+
# mandatory_attribution :text
18+
# output_type :integer default(3), not null
19+
# output_type_description :string
20+
# personal_data :boolean
21+
# release_date :datetime
22+
# sensitive_data :boolean
23+
# title :string not null
24+
# created_at :datetime not null
25+
# updated_at :datetime not null
26+
# mime_type_id :integer
27+
# plan_id :integer
28+
#
29+
# Indexes
30+
#
31+
# index_research_outputs_on_output_type (output_type)
32+
# index_research_outputs_on_plan_id (plan_id)
33+
#
34+
class ResearchOutput < ApplicationRecord
35+
36+
include Identifiable
37+
include ValidationMessages
38+
39+
enum output_type: %i[audiovisual collection data_paper dataset event image
40+
interactive_resource model_representation physical_object
41+
service software sound text workflow other]
42+
43+
enum access: %i[open embargoed restricted closed]
44+
45+
# ================
46+
# = Associations =
47+
# ================
48+
49+
belongs_to :plan, optional: true
50+
belongs_to :mime_type, optional: true
51+
52+
# ===============
53+
# = Validations =
54+
# ===============
55+
56+
validates_presence_of :output_type, :access, :title, message: PRESENCE_MESSAGE
57+
validates_uniqueness_of :title, :abbreviation, scope: :plan_id
58+
59+
# Ensure presence of the :output_type_description if the user selected 'other'
60+
validates_presence_of :output_type_description, if: -> { other? }, message: PRESENCE_MESSAGE
61+
# Ensure that :coverage_start comes before :coverage_end
62+
validate :end_date_after_start_date
63+
64+
# ====================
65+
# = Instance methods =
66+
# ====================
67+
68+
# :mime_type is only applicable for certain :output_types
69+
# This method returns the applicable :mime_types
70+
def available_mime_types
71+
cat = %w[audio video] if audiovisual? || sound?
72+
cat = %w[image] if image?
73+
cat = %w[model] if model_representation?
74+
cat = %w[text] if data_paper? || dataset? || text?
75+
76+
cat.present? ? MimeType.where(category: cat).order(:description) : []
77+
end
78+
79+
# TODO: placeholders for once the License, Repository, Metadata Standard and
80+
# Resource Type Lookups feature is built.
81+
#
82+
# Be sure to add the scheme in the appropriate upgrade task (and to the
83+
# seed.rb as well)
84+
def licenses
85+
# scheme = IdentifierScheme.find_by(name: '[name of license scheme]')
86+
# return [] unless scheme.present?
87+
# identifiers.select { |id| id.identifier_scheme = scheme }
88+
[]
89+
end
90+
91+
def repositories
92+
# scheme = IdentifierScheme.find_by(name: '[name of repository scheme]')
93+
# return [] unless scheme.present?
94+
# identifiers.select { |id| id.identifier_scheme = scheme }
95+
[]
96+
end
97+
98+
def metadata_standards
99+
# scheme = IdentifierScheme.find_by(name: '[name of openaire scheme]')
100+
# return [] unless scheme.present?
101+
# identifiers.select { |id| id.identifier_scheme = scheme }
102+
[]
103+
end
104+
105+
def resource_types
106+
# scheme = IdentifierScheme.find_by(name: '[name of resource_type scheme]')
107+
# return [] unless scheme.present?
108+
# identifiers.select { |id| id.identifier_scheme = scheme }
109+
[]
110+
end
111+
112+
private
113+
114+
# Validation to prevent end date from coming before the start date
115+
def end_date_after_start_date
116+
# allow nil values
117+
return true if coverage_end.blank? || coverage_start.blank?
118+
119+
errors.add(:coverage_end, _("must be after the start date")) if coverage_end < coverage_start
120+
end
121+
122+
end

bin/setup

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,21 @@ chdir APP_ROOT do
1717
system! 'gem install bundler --conservative'
1818
system('bundle check') || system!('bundle install')
1919

20-
# Install JavaScript dependencies if using Yarn
21-
# system('bin/yarn')
22-
23-
# puts "\n== Copying sample files =="
24-
# unless File.exist?('config/database.yml')
25-
# cp 'config/database.yml.sample', 'config/database.yml'
26-
# end
20+
puts "\n== Copying sample files =="
21+
%w[
22+
config/database.yml.sample
23+
config/initializers/wicked_pdf.rb.example
24+
].each do |file|
25+
new_file .gsub('.sample', '').gsub('.example', '')
26+
cp file, new_file unless File.exist?(new_file)
27+
end
2728

2829
puts "\n== Preparing database =="
2930
system! 'bin/rails db:setup'
3031

32+
puts "\n== Fetching mime types and adding to database =="
33+
system! 'bin/rails mime_types:load'
34+
3135
puts "\n== Removing old logs and tempfiles =="
3236
system! 'bin/rails log:clear tmp:clear'
3337

config/initializers/external_apis/open_aire.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# These configuration settings are used to communicate with the
44
# Open Aire Research Project Registry API. For more information about
5-
# the API and to verify that your configuration settings are correct,
5+
# the API and to verify that your configuration settings are correct.
66
Rails.configuration.x.open_aire.api_base_url = "https://api.openaire.eu/"
77
# The api_url should contain `%s. This is where the funder is appended!
88
Rails.configuration.x.open_aire.search_path = "projects/dspace/%s/ALL/ALL"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class CreateResearchOutputs < ActiveRecord::Migration[5.2]
2+
def change
3+
create_table :research_outputs do |t|
4+
t.integer :plan_id, index: true
5+
t.integer :output_type, null: false, index: true, default: 3
6+
t.string :output_type_description
7+
t.string :title, null: false
8+
t.string :abbreviation
9+
t.integer :display_order
10+
t.boolean :is_default
11+
t.text :description
12+
t.integer :mime_type_id
13+
t.integer :access, null: false, default: 0
14+
t.datetime :release_date
15+
t.boolean :personal_data
16+
t.boolean :sensitive_data
17+
t.bigint :byte_size
18+
t.text :mandatory_attribution
19+
t.datetime :coverage_start
20+
t.datetime :coverage_end
21+
t.string :coverage_region
22+
t.timestamps null: false
23+
end
24+
end
25+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CreateMimeTypes < ActiveRecord::Migration[5.2]
2+
def change
3+
create_table :mime_types do |t|
4+
t.string :description, null: false
5+
t.string :category, null: false
6+
t.string :value, null: false, index: true
7+
t.timestamps
8+
end
9+
end
10+
end

db/schema.rb

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema.define(version: 2020_11_13_174910) do
13+
ActiveRecord::Schema.define(version: 2020_11_19_210343) do
1414

1515
create_table "annotations", id: :integer, force: :cascade do |t|
1616
t.integer "question_id"
@@ -157,6 +157,15 @@
157157
t.boolean "default_language"
158158
end
159159

160+
create_table "mime_types", force: :cascade do |t|
161+
t.string "description", null: false
162+
t.string "category", null: false
163+
t.string "value", null: false
164+
t.datetime "created_at", null: false
165+
t.datetime "updated_at", null: false
166+
t.index ["value"], name: "index_mime_types_on_value"
167+
end
168+
160169
create_table "notes", id: :integer, force: :cascade do |t|
161170
t.integer "user_id"
162171
t.text "text"
@@ -357,6 +366,31 @@
357366
t.integer "super_region_id"
358367
end
359368

369+
create_table "research_outputs", force: :cascade do |t|
370+
t.integer "plan_id"
371+
t.integer "output_type", default: 3, null: false
372+
t.string "output_type_description"
373+
t.string "title", null: false
374+
t.string "abbreviation"
375+
t.integer "display_order"
376+
t.boolean "is_default"
377+
t.text "description"
378+
t.integer "mime_type_id"
379+
t.integer "access", default: 0, null: false
380+
t.datetime "release_date"
381+
t.boolean "personal_data"
382+
t.boolean "sensitive_data"
383+
t.bigint "byte_size"
384+
t.text "mandatory_attribution"
385+
t.datetime "coverage_start"
386+
t.datetime "coverage_end"
387+
t.string "coverage_region"
388+
t.datetime "created_at", null: false
389+
t.datetime "updated_at", null: false
390+
t.index ["output_type"], name: "index_research_outputs_on_output_type"
391+
t.index ["plan_id"], name: "index_research_outputs_on_plan_id"
392+
end
393+
360394
create_table "roles", id: :integer, force: :cascade do |t|
361395
t.integer "user_id"
362396
t.integer "plan_id"

lib/tasks/mime_types.rake

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# frozen_string_literal: true
2+
3+
require 'httparty'
4+
5+
namespace :mime_types do
6+
7+
IANA_BASE_URL = "https://www.iana.org/assignments/media-types".freeze
8+
9+
desc "Fetch all of the latest MIME types and load into the DB"
10+
task load: :environment do
11+
%w[application.csv audio.csv font.csv image.csv message.csv model.csv
12+
multipart.csv text.csv video.csv].each do |file_name|
13+
fetch_and_process_mime_type_file(url: "#{IANA_BASE_URL}/#{file_name}")
14+
end
15+
end
16+
17+
def fetch_and_process_mime_type_file(url:)
18+
p "Processing #{url}"
19+
body = fetch_csv_file(url: url)
20+
p " Unable to process the specified URL" unless body.present?
21+
22+
csv = CSV.parse(body, headers: true, force_quotes: true, encoding: 'iso-8859-1:utf-8')
23+
p " Invalid CSV format. Expecting a 'Name' and 'Template' column" unless csv.headers.include?("Name") &&
24+
csv.headers.include?("Template")
25+
process_mime_file(csv: csv)
26+
p " Done"
27+
rescue StandardError => e
28+
p " Error processing CSV content - #{e.message}"
29+
end
30+
31+
def process_mime_file(csv:)
32+
return unless csv.is_a?(CSV::Table)
33+
34+
csv.each do |line|
35+
next unless line["Template"].present? && line["Name"].present?
36+
37+
type = MimeType.find_or_initialize_by(value: line["Template"].downcase)
38+
type.description = line["Name"]
39+
type.category = line["Template"].split("/").first.downcase
40+
type.save
41+
end
42+
end
43+
44+
def fetch_csv_file(url:)
45+
return nil unless url.present?
46+
47+
payload = HTTParty.get(url, debug: false)
48+
return nil unless payload.code == 200
49+
50+
payload.body
51+
end
52+
53+
end

lib/tasks/v3.rake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ namespace :v3 do
77
Rake::Task["v3:fix_funder_ids"].execute
88
end
99

10+
desc "Upgrade from v3.0.0 to v3.1.0"
11+
task upgrade_3_1_0: :environment do
12+
Rake::Task["mime_types:load"].execute
13+
end
14+
1015
# Set any records with a nil `language_id` to the default language
1116
desc "Change nil language_id entries into the default language"
1217
task ensure_default_languages: :environment do

spec/factories/mime_types.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
# == Schema Information
4+
#
5+
# Table name: mime_types
6+
#
7+
# id :bigint not null, primary key
8+
# category :string not null
9+
# description :string not null
10+
# value :string not null
11+
# created_at :datetime not null
12+
# updated_at :datetime not null
13+
#
14+
# Indexes
15+
#
16+
# index_mime_types_on_value (value)
17+
#
18+
FactoryBot.define do
19+
factory :mime_type do
20+
category { %w[application audio audio image text video].sample }
21+
description { Faker::Lorem.sentence }
22+
value { "#{category}/#{Faker::Lorem.word}" }
23+
end
24+
end

0 commit comments

Comments
 (0)