Skip to content

Commit 1234096

Browse files
Merge to master: Release 2.3.2 - Submissions endpoint pagination and fixes (#52)
* add get submission all including all properties test * extract and use submission_include_params where we use submission.bring * use retrieve_submissions helper in the :acronym/submissions endpoint
1 parent eb9103b commit 1234096

11 files changed

Lines changed: 329 additions & 77 deletions

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ GIT
5353

5454
GIT
5555
remote: https://github.com/ontoportal-lirmm/ontologies_linked_data.git
56-
revision: 0d6632bb39c1d24a930fe088bc464c3a51d68c9b
56+
revision: f44f7baa96eb3ee10dfab4a8aca154161ba7dd89
5757
branch: master
5858
specs:
5959
ontologies_linked_data (0.0.1)
@@ -112,7 +112,7 @@ GEM
112112
bcrypt_pbkdf (1.1.0)
113113
bigdecimal (1.4.2)
114114
builder (3.2.4)
115-
capistrano (3.17.3)
115+
capistrano (3.18.0)
116116
airbrussh (>= 1.0.0)
117117
i18n
118118
rake (>= 10.0.0)

controllers/admin_controller.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class AdminController < ApplicationController
6868
latest = ont.latest_submission(status: :any)
6969
error 404, "Ontology #{params["acronym"]} contains no submissions" if latest.nil?
7070
check_last_modified(latest)
71-
latest.bring(*OntologySubmission.goo_attrs_to_load(includes_param))
71+
latest.bring(*submission_include_params)
7272
NcboCron::Models::OntologySubmissionParser.new.queue_submission(latest, actions)
7373
halt 204
7474
end
@@ -84,7 +84,7 @@ class AdminController < ApplicationController
8484
latest = ont.latest_submission(status: :any)
8585
end
8686
check_last_modified(latest) if latest
87-
latest.bring(*OntologySubmission.goo_attrs_to_load(includes_param)) if latest
87+
latest.bring(*submission_include_params) if latest
8888
reply(latest || {})
8989
end
9090

controllers/ontologies_controller.rb

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,12 @@ class OntologiesController < ApplicationController
3838
else
3939
latest = ont.latest_submission(status: :any)
4040
end
41-
check_last_modified(latest) if latest
42-
# When asking to display all metadata, we are using bring_remaining which is more performant than including all metadata (remove this when the query to get metadata will be fixed)
41+
4342
if latest
44-
if includes_param.first == :all
45-
# Bring what we need to display all attr of the submission
46-
latest.bring_remaining
47-
latest.bring({:contact=>[:name, :email],
48-
:ontology=>[:acronym, :name, :administeredBy, :group, :viewingRestriction, :doNotUpdate, :flat,
49-
:hasDomain, :summaryOnly, :acl, :viewOf, :ontologyType],
50-
:submissionStatus=>[:code], :hasOntologyLanguage=>[:acronym]})
51-
else
52-
latest.bring(*OntologySubmission.goo_attrs_to_load(includes_param))
53-
end
43+
check_last_modified(latest)
44+
latest.bring(*submission_include_params)
5445
end
55-
#remove the whole previous if block and replace by it: latest.bring(*OntologySubmission.goo_attrs_to_load(includes_param)) if latest
46+
5647
reply(latest || {})
5748
end
5849

@@ -62,7 +53,7 @@ class OntologiesController < ApplicationController
6253
patch '/:acronym/latest_submission' do
6354
ont = Ontology.find(params["acronym"]).first
6455
error 422, "You must provide an existing `acronym` to patch" if ont.nil?
65-
56+
6657
submission = ont.latest_submission(status: :any)
6758

6859
submission.bring(*OntologySubmission.attributes)

controllers/ontology_submissions_controller.rb

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
class OntologySubmissionsController < ApplicationController
22
get "/submissions" do
33
check_last_modified_collection(LinkedData::Models::OntologySubmission)
4-
#using appplication_helper method
5-
options = {also_include_views: params["also_include_views"], status: (params["include_status"] || "ANY")}
6-
reply retrieve_latest_submissions(options).values
4+
options = {
5+
also_include_views: params["also_include_views"],
6+
status: (params["include_status"] || "ANY")
7+
}
8+
subs = retrieve_latest_submissions(options)
9+
subs = subs.values unless page?
10+
# Force to show ontology reviews, notes and projects by default only for this request
11+
LinkedData::Models::Ontology.serialize_default(*(LinkedData::Models::Ontology.hypermedia_settings[:serialize_default] + [:reviews, :notes, :projects]))
12+
reply subs
713
end
814

915
##
@@ -19,22 +25,18 @@ class OntologySubmissionsController < ApplicationController
1925
##
2026
# Display all submissions of an ontology
2127
get do
22-
ont = Ontology.find(params["acronym"]).include(:acronym).first
28+
ont = Ontology.find(params["acronym"]).include(:acronym, :administeredBy, :acl, :viewingRestriction).first
2329
error 422, "Ontology #{params["acronym"]} does not exist" unless ont
2430
check_last_modified_segment(LinkedData::Models::OntologySubmission, [ont.acronym])
25-
if includes_param.first == :all
26-
# When asking to display all metadata, we are using bring_remaining which is more performant than including all metadata (remove this when the query to get metadata will be fixed)
27-
ont.bring(submissions: [:released, :creationDate, :status, :submissionId,
28-
{:contact=>[:name, :email], :ontology=>[:administeredBy, :acronym, :name, :summaryOnly, :ontologyType, :viewingRestriction, :acl, :group, :hasDomain, :views, :viewOf, :flat],
29-
:submissionStatus=>[:code], :hasOntologyLanguage=>[:acronym]}, :submissionStatus])
30-
31-
ont.submissions.each do |sub|
32-
sub.bring_remaining
33-
end
34-
else
35-
ont.bring(submissions: OntologySubmission.goo_attrs_to_load(includes_param))
36-
end
37-
reply ont.submissions.sort {|a,b| b.submissionId.to_i <=> a.submissionId.to_i } # descending order of submissionId
31+
check_access(ont)
32+
options = {
33+
also_include_views: true,
34+
status: (params["include_status"] || "ANY"),
35+
ontology: params["acronym"]
36+
}
37+
subs = retrieve_submissions(options)
38+
39+
reply subs.sort {|a,b| b.submissionId.to_i <=> a.submissionId.to_i } # descending order of submissionId
3840
end
3941

4042
##
@@ -53,7 +55,7 @@ class OntologySubmissionsController < ApplicationController
5355
ont.bring(:submissions)
5456
ont_submission = ont.submission(params["ontology_submission_id"])
5557
error 404, "`submissionId` not found" if ont_submission.nil?
56-
ont_submission.bring(*OntologySubmission.goo_attrs_to_load(includes_param))
58+
ont_submission.bring(*submission_include_params)
5759
reply ont_submission
5860
end
5961

helpers/access_control_helper.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ module AccessControlHelper
1010
def check_access(obj)
1111
return obj unless LinkedData.settings.enable_security
1212
if obj.is_a?(Enumerable)
13-
if obj.first.is_a?(LinkedData::Models::Base) && obj.first.access_based_on?
14-
check_access(obj.first)
15-
else
1613
filter_access(obj)
17-
end
1814
else
1915
if obj.respond_to?(:read_restricted?) && obj.read_restricted?
2016
readable = obj.readable?(env["REMOTE_USER"])

helpers/application_helper.rb

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ def populate_from_params(obj, params)
5252
value = is_arr ? value : [value]
5353
new_value = []
5454
value.each do |cls|
55+
if uri_as_needed(cls["ontology"]).nil?
56+
new_value << cls
57+
next
58+
end
5559
sub = LinkedData::Models::Ontology.find(uri_as_needed(cls["ontology"])).first.latest_submission
5660
new_value << LinkedData::Models::Class.find(cls["class"]).in(sub).first
5761
end
@@ -356,40 +360,16 @@ def replace_url_prefix(id)
356360
end
357361

358362
def retrieve_latest_submissions(options = {})
359-
status = (options[:status] || "RDF").to_s.upcase
360-
include_ready = status.eql?("READY") ? true : false
361-
status = "RDF" if status.eql?("READY")
362-
any = true if status.eql?("ANY")
363-
include_views = options[:also_include_views] || false
364-
includes = OntologySubmission.goo_attrs_to_load(includes_param)
365-
366-
includes << :submissionStatus unless includes.include?(:submissionStatus)
367-
if any
368-
submissions_query = OntologySubmission.where
369-
else
370-
submissions_query = OntologySubmission.where(submissionStatus: [ code: status])
371-
end
363+
submissions = retrieve_submissions(options)
372364

373-
submissions_query = submissions_query.filter(Goo::Filter.new(ontology: [:viewOf]).unbound) unless include_views
374-
submissions_query = submissions_query.filter(filter) if filter?
375-
# When asking to display all metadata, we are using bring_remaining on each submission. Slower but best way to retrieve all attrs
376-
if includes_param.first == :all
377-
includes = [:submissionId, {:contact=>[:name, :email], :ontology=>[:administeredBy, :acronym, :name, :summaryOnly, :ontologyType, :viewingRestriction, :acl,
378-
:group, :hasDomain, :views, :viewOf, :flat], :submissionStatus=>[:code], :hasOntologyLanguage=>[:acronym]}, :submissionStatus]
379-
end
380-
submissions = submissions_query.include(includes).to_a
381-
382-
# Figure out latest parsed submissions using all submissions
383-
latest_submissions = {}
365+
latest_submissions = page? ? submissions : {} # latest_submission doest not work with pagination
384366
submissions.each do |sub|
385-
# To retrieve all metadata, but slow when a lot of ontologies
386-
if includes_param.first == :all
387-
sub.bring_remaining
367+
unless page?
368+
next if include_ready?(options) && !sub.ready?
369+
next if sub.ontology.nil?
370+
latest_submissions[sub.ontology.acronym] ||= sub
371+
latest_submissions[sub.ontology.acronym] = sub if sub.submissionId.to_i > latest_submissions[sub.ontology.acronym].submissionId.to_i
388372
end
389-
next if include_ready && !sub.ready?
390-
next if sub.ontology.nil?
391-
latest_submissions[sub.ontology.acronym] ||= sub
392-
latest_submissions[sub.ontology.acronym] = sub if sub.submissionId.to_i > latest_submissions[sub.ontology.acronym].submissionId.to_i
393373
end
394374
latest_submissions
395375
end

helpers/request_params_helper.rb

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ def settings_params(klass)
1313
[attributes, page, size, order_by, bring_unmapped]
1414
end
1515

16+
def page?
17+
!params[:page].nil?
18+
end
19+
1620
def is_set?(param)
1721
!param.nil? && param != ""
1822
end
@@ -25,6 +29,38 @@ def filter
2529
build_filter
2630
end
2731

32+
def apply_filters(object, query)
33+
attributes_to_filter = object.attributes(:all).select{|x| params.keys.include?(x.to_s)}
34+
filters = attributes_to_filter.map {|key| [key, params[key]&.split(',')]}.to_h
35+
add_direct_filters(filters, query)
36+
end
37+
38+
def apply_submission_filters(query)
39+
40+
filters = {
41+
naturalLanguage: params[:naturalLanguage]&.split(',') , #%w[http://lexvo.org/id/iso639-3/fra http://lexvo.org/id/iso639-3/eng],
42+
hasOntologyLanguage_acronym: params[:hasOntologyLanguage]&.split(',') , #%w[OWL SKOS],
43+
ontology_hasDomain_acronym: params[:hasDomain]&.split(',') , #%w[Crop Vue_francais],
44+
ontology_group_acronym: params[:group]&.split(','), #%w[RICE CROP],
45+
isOfType: params[:isOfType]&.split(','), #["http://omv.ontoware.org/2005/05/ontology#Vocabulary"],
46+
hasFormalityLevel: params[:hasFormalityLevel]&.split(','), #["http://w3id.org/nkos/nkostype#thesaurus"],
47+
ontology_viewingRestriction: params[:viewingRestriction]&.split(','), #["private"]
48+
}
49+
inverse_filters = {
50+
status: params[:status], #"retired",
51+
submissionStatus: params[:submissionStatus] #"RDF",
52+
}
53+
54+
query = add_direct_filters(filters, query)
55+
56+
query = add_inverse_filters(inverse_filters, query)
57+
58+
query = add_acronym_name_filters(query)
59+
60+
add_order_by_patterns(query)
61+
end
62+
63+
2864
def get_order_by_from(params, default_order = :asc)
2965
if is_set?(params['sortby'])
3066
orders = (params["order"] || default_order.to_s).split(',')
@@ -50,6 +86,67 @@ def bring_unmapped_to(page_data, sub, klass)
5086
end
5187

5288
private
89+
def extract_attr(key)
90+
attr, sub_attr, sub_sub_attr = key.to_s.split('_')
91+
92+
return attr.to_sym unless sub_attr
93+
94+
return {attr.to_sym => [sub_attr.to_sym]} unless sub_sub_attr
95+
96+
{attr.to_sym => [sub_attr.to_sym => sub_sub_attr.to_sym]}
97+
end
98+
99+
def add_direct_filters(filters, query)
100+
filters.each do |key, values|
101+
attr = extract_attr(key)
102+
next if Array(values).empty?
103+
104+
filter = Goo::Filter.new(attr).regex(values.first)
105+
values.drop(1).each do |v|
106+
filter = filter.or(Goo::Filter.new(attr).regex(v))
107+
end
108+
query = query.filter(filter)
109+
end
110+
query
111+
end
112+
113+
def add_inverse_filters(inverse_filters, query)
114+
inverse_filters.each do |key, value|
115+
attr = extract_attr(key)
116+
next unless value
117+
118+
filter = Goo::Filter.new(attr).regex("^(?:(?!#{value}).)*$")
119+
query = query.filter(filter)
120+
end
121+
query
122+
end
123+
124+
def add_acronym_name_filters(query)
125+
if params[:acronym]
126+
filter = Goo::Filter.new(extract_attr(:ontology_acronym)).regex(params[:acronym])
127+
if params[:name]
128+
filter.or(Goo::Filter.new(extract_attr(:ontology_name)).regex(params[:name]))
129+
end
130+
query = query.filter(filter)
131+
elsif params[:name]
132+
filter = Goo::Filter.new(extract_attr(:ontology_name)).regex(params[:name])
133+
query = query.filter(filter)
134+
end
135+
query
136+
end
137+
138+
def add_order_by_patterns(query)
139+
if params[:order_by]
140+
attr, sub_attr = params[:order_by].to_s.split('_')
141+
if sub_attr
142+
order_pattern = { attr.to_sym => { sub_attr.to_sym => (sub_attr.eql?("name") ? :asc : :desc) } }
143+
else
144+
order_pattern = { attr.to_sym => :desc }
145+
end
146+
query = query.order_by(order_pattern)
147+
end
148+
query
149+
end
53150

54151
def sort_order_item(param, order)
55152
[param.to_sym, order.to_sym]

helpers/submission_helper.rb

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
require 'sinatra/base'
2+
3+
module Sinatra
4+
module Helpers
5+
module SubmissionHelper
6+
def submission_include_params
7+
# When asking to display all metadata, we are using bring_remaining on each submission. Slower but best way to retrieve all attrs
8+
includes = OntologySubmission.goo_attrs_to_load(includes_param)
9+
if includes.find{|v| v.is_a?(Hash) && v.keys.include?(:ontology)}
10+
includes << {:ontology=>[:administeredBy, :acronym, :name, :viewingRestriction, :group, :hasDomain,:notes, :reviews, :projects,:acl, :viewOf]}
11+
end
12+
13+
if includes.find{|v| v.is_a?(Hash) && v.keys.include?(:contact)}
14+
includes << {:contact=>[:name, :email]}
15+
end
16+
includes
17+
end
18+
19+
def submission_attributes_all
20+
out = [LinkedData::Models::OntologySubmission.embed_values_hash]
21+
out << {:contact=>[:name, :email]}
22+
out << {:ontology=>[:acronym, :name, :administeredBy, :group, :viewingRestriction, :doNotUpdate, :flat,
23+
:hasDomain, :summaryOnly, :acl, :viewOf, :ontologyType]}
24+
25+
out
26+
end
27+
28+
def retrieve_submissions(options)
29+
status = (options[:status] || "RDF").to_s.upcase
30+
status = "RDF" if status.eql?("READY")
31+
ontology_acronym = options[:ontology]
32+
any = status.eql?("ANY")
33+
include_views = options[:also_include_views] || false
34+
includes, page, size, order_by, _ = settings_params(LinkedData::Models::OntologySubmission)
35+
includes << :submissionStatus unless includes.include?(:submissionStatus)
36+
37+
submissions_query = LinkedData::Models::OntologySubmission
38+
submissions_query = submissions_query.where(ontology: [acronym: ontology_acronym]) if ontology_acronym
39+
40+
if any
41+
submissions_query = submissions_query.where unless ontology_acronym
42+
else
43+
submissions_query = submissions_query.where({ submissionStatus: [code: status] })
44+
end
45+
46+
submissions_query = apply_submission_filters(submissions_query)
47+
submissions_query = submissions_query.filter(Goo::Filter.new(ontology: [:viewOf]).unbound) unless include_views
48+
submissions_query = submissions_query.filter(filter) if filter?
49+
50+
51+
submissions = submissions_query.include(submission_include_params)
52+
if page?
53+
submissions.page(page, size).all
54+
else
55+
submissions.to_a
56+
end
57+
end
58+
59+
def include_ready?(options)
60+
options[:status] && options[:status].to_s.upcase.eql?("READY")
61+
end
62+
63+
end
64+
end
65+
end
66+
67+
helpers Sinatra::Helpers::SubmissionHelper

0 commit comments

Comments
 (0)