iqvoc 4.14.5 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/Gemfile +9 -16
  4. data/Gemfile.lock +313 -257
  5. data/README.md +1 -1
  6. data/app/aides/entity_logger.rb +27 -0
  7. data/app/aides/maker.rb +1 -1
  8. data/app/aides/origin.rb +1 -1
  9. data/app/aides/{rdfapi.rb → rdf_api.rb} +1 -1
  10. data/app/aides/skos_importer.rb +1 -1
  11. data/app/assets/javascripts/iqvoc/iqvoc.js +4 -3
  12. data/app/assets/javascripts/iqvoc/treeview.js +3 -3
  13. data/app/assets/stylesheets/_framework.scss +1 -1
  14. data/app/controllers/collections/alphabetical_controller.rb +75 -0
  15. data/app/controllers/collections/expired_controller.rb +37 -0
  16. data/app/controllers/collections_controller.rb +22 -28
  17. data/app/controllers/concepts/alphabetical_controller.rb +4 -6
  18. data/app/controllers/concepts/expired_controller.rb +1 -1
  19. data/app/controllers/concepts/hierarchical_controller.rb +18 -15
  20. data/app/controllers/concepts_controller.rb +0 -3
  21. data/app/controllers/concepts_movement_controller.rb +1 -1
  22. data/app/controllers/concerns/controller_extensions.rb +15 -0
  23. data/app/controllers/dashboard_controller.rb +1 -1
  24. data/app/controllers/exports_controller.rb +17 -8
  25. data/app/controllers/rdf_controller.rb +0 -2
  26. data/app/controllers/remote_labels_controller.rb +0 -2
  27. data/app/controllers/search_results_controller.rb +59 -43
  28. data/app/helpers/concepts_helper.rb +2 -2
  29. data/app/helpers/navigation_helper.rb +7 -7
  30. data/app/helpers/rdf_helper.rb +2 -0
  31. data/app/jobs/export_job.rb +4 -7
  32. data/app/models/collection/base.rb +6 -8
  33. data/app/models/collection/member/skos/base.rb +2 -2
  34. data/app/models/collection/skos/base.rb +1 -1
  35. data/app/models/collection/skos/unordered.rb +1 -1
  36. data/app/models/collection/unordered.rb +2 -2
  37. data/app/models/concept/base.rb +2 -10
  38. data/app/models/concept/relation/base.rb +1 -1
  39. data/app/models/concept/relation/skos/base.rb +2 -2
  40. data/app/models/concept/relation/skos/broader/base.rb +2 -2
  41. data/app/models/concept/relation/skos/broader/mono.rb +1 -1
  42. data/app/models/concept/relation/skos/broader/poly.rb +1 -1
  43. data/app/models/concept/relation/skos/narrower/base.rb +1 -1
  44. data/app/models/concept/relation/skos/related.rb +1 -1
  45. data/app/models/concept/skos/base.rb +1 -1
  46. data/app/models/concept/skos/scheme.rb +2 -2
  47. data/app/models/concept/validations.rb +14 -0
  48. data/app/models/concerns/expirable.rb +14 -0
  49. data/app/models/export.rb +21 -9
  50. data/app/models/label/base.rb +19 -1
  51. data/app/models/label/skos/base.rb +1 -1
  52. data/app/models/labeling/base.rb +12 -0
  53. data/app/models/labeling/skos/alt_label.rb +1 -1
  54. data/app/models/labeling/skos/base.rb +4 -4
  55. data/app/models/labeling/skos/hidden_label.rb +1 -1
  56. data/app/models/labeling/skos/pref_label.rb +1 -1
  57. data/app/models/match/skos/base.rb +3 -3
  58. data/app/models/match/skos/broad_match.rb +2 -2
  59. data/app/models/match/skos/close_match.rb +1 -1
  60. data/app/models/match/skos/exact_match.rb +1 -1
  61. data/app/models/match/skos/mapping_relation.rb +1 -1
  62. data/app/models/match/skos/narrow_match.rb +2 -2
  63. data/app/models/match/skos/related_match.rb +1 -1
  64. data/app/models/note/base.rb +2 -2
  65. data/app/models/note/rdfs/see_also.rb +1 -1
  66. data/app/models/note/skos/base.rb +4 -4
  67. data/app/models/note/skos/change_note.rb +2 -2
  68. data/app/models/note/skos/definition.rb +1 -1
  69. data/app/models/note/skos/editorial_note.rb +1 -1
  70. data/app/models/note/skos/example.rb +1 -1
  71. data/app/models/note/skos/history_note.rb +1 -1
  72. data/app/models/note/skos/scope_note.rb +1 -1
  73. data/app/presenters/alphabetical_search_result.rb +2 -2
  74. data/app/services/rdf_sync_service.rb +1 -1
  75. data/app/uploaders/base.rb +4 -3
  76. data/app/view_models/concept_view.rb +1 -1
  77. data/app/views/collections/_data.html.erb +1 -1
  78. data/app/views/collections/_form.html.erb +14 -2
  79. data/app/views/collections/alphabetical/_search_result.html.erb +17 -0
  80. data/app/views/collections/alphabetical/_search_result_remote.html.erb +14 -0
  81. data/app/views/collections/alphabetical/index.html.erb +23 -0
  82. data/app/views/collections/edit.html.erb +1 -1
  83. data/app/views/collections/expired/index.html.erb +23 -0
  84. data/app/views/collections/index.html.erb +1 -1
  85. data/app/views/collections/new.html.erb +1 -1
  86. data/app/views/collections/show_published.html.erb +1 -1
  87. data/app/views/collections/show_unpublished.html.erb +1 -1
  88. data/app/views/collections/sidebars/_plural.html.erb +28 -0
  89. data/app/views/collections/sidebars/_singular.html.erb +22 -0
  90. data/app/views/concepts/_form.html.erb +1 -1
  91. data/app/views/concepts/alphabetical/index.html.erb +1 -1
  92. data/app/views/concepts/expired/index.html.erb +1 -1
  93. data/app/views/concepts/glance.html.erb +1 -1
  94. data/app/views/concepts/scheme/edit.html.erb +1 -1
  95. data/app/views/concepts/sidebars/_plural.html.erb +1 -1
  96. data/app/views/concepts/sidebars/_singular.html.erb +1 -1
  97. data/app/views/dashboard/glance.html.erb +1 -1
  98. data/app/views/exports/index.html.erb +5 -1
  99. data/app/views/exports/show.html.erb +1 -1
  100. data/app/views/partials/collection/_inline_base.html.erb +4 -0
  101. data/app/views/search_results/_sidebar.html.erb +1 -1
  102. data/config/application.rb +7 -2
  103. data/config/ci.rb +20 -0
  104. data/config/database.yml +15 -21
  105. data/config/database.yml.postgresql +13 -20
  106. data/config/engine.rb +1 -0
  107. data/config/environments/development.rb +1 -1
  108. data/config/environments/production.rb +1 -1
  109. data/config/environments/test.rb +1 -1
  110. data/config/initializers/content_security_policy.rb +6 -2
  111. data/config/initializers/filter_parameter_logging.rb +4 -4
  112. data/config/initializers/new_framework_defaults_7_1.rb +280 -0
  113. data/config/initializers/new_framework_defaults_8_0.rb +30 -0
  114. data/config/initializers/new_framework_defaults_8_1.rb +74 -0
  115. data/config/initializers/permissions_policy.rb +11 -9
  116. data/config/initializers/zeitwerk.rb +1 -3
  117. data/config/locales/de.yml +4 -1
  118. data/config/locales/en.yml +4 -1
  119. data/config/locales/pt.yml +2 -1
  120. data/config/puma.rb +34 -35
  121. data/config/routes.rb +3 -1
  122. data/db/migrate/20110510162719_use_mono_hierarchy_instead_of_poly_hierarchy.rb +2 -2
  123. data/db/migrate/20130227145825_fix_collection_type.rb +3 -3
  124. data/db/migrate/20130502151221_fix_collection_member_types.rb +1 -1
  125. data/db/migrate/20250218160045_adapt_zeitwerk_naming_to_iqvoc.rb +25 -0
  126. data/db/migrate/20250326182601_adapt_zeitwerk_skos_naming_to_instance_configuration.rb +11 -0
  127. data/db/schema.rb +100 -1
  128. data/iqvoc.gemspec +4 -4
  129. data/lib/iqvoc/configuration/collection.rb +16 -4
  130. data/lib/iqvoc/configuration/concept.rb +22 -18
  131. data/lib/iqvoc/configuration/core.rb +9 -23
  132. data/lib/iqvoc/configuration/label.rb +1 -1
  133. data/lib/iqvoc/environments/development.rb +62 -57
  134. data/lib/iqvoc/environments/production.rb +70 -67
  135. data/lib/iqvoc/environments/test.rb +44 -38
  136. data/lib/iqvoc/version.rb +1 -1
  137. data/test/controllers/concepts_movement_controller_test.rb +14 -14
  138. data/test/controllers/hierarchy_test.rb +0 -1
  139. data/test/controllers/reverse_match_test.rb +6 -6
  140. data/test/integration/alphabetical_test.rb +5 -5
  141. data/test/integration/browse_concepts_and_labels_test.rb +4 -4
  142. data/test/integration/client_edit_concept_test.rb +1 -1
  143. data/test/integration/collection_browsing_test.rb +2 -2
  144. data/test/integration/collection_circularity_test.rb +10 -10
  145. data/test/integration/collection_test.rb +79 -0
  146. data/test/integration/concept_browsing_test.rb +3 -3
  147. data/test/integration/concept_collection_assignment_test.rb +4 -4
  148. data/test/integration/concept_scheme_browsing_test.rb +7 -7
  149. data/test/integration/edit_collections_test.rb +1 -1
  150. data/test/integration/edit_concepts_test.rb +2 -2
  151. data/test/integration/instance_configuration_browsing_test.rb +1 -1
  152. data/test/integration/note_annotations_test.rb +2 -2
  153. data/test/integration/reverse_match_job_test.rb +9 -9
  154. data/test/integration/search_test.rb +20 -10
  155. data/test/integration/tree_test.rb +5 -5
  156. data/test/integration/untranslated_test.rb +2 -2
  157. data/test/integration_test_helper.rb +7 -0
  158. data/test/models/concept_scheme_test.rb +6 -6
  159. data/test/models/concept_test.rb +38 -38
  160. data/test/models/deep_cloning_test.rb +6 -6
  161. data/test/models/note_test.rb +4 -4
  162. data/test/models/rdf_sync_test.rb +1 -1
  163. data/test/models/rdfapi_test.rb +24 -24
  164. data/test/models/skos_collection_import_test.rb +3 -3
  165. data/test/models/skos_import_test.rb +4 -4
  166. metadata +44 -32
  167. data/app/views/collections/_sidebar.html.erb +0 -20
  168. data/config/environments/heroku.rb +0 -81
  169. data/config/initializers/heroku.rb +0 -24
  170. data/config/secrets.yml +0 -35
  171. /data/{app/helpers → lib}/iqvoc_module_helper.rb +0 -0
  172. /data/{app/models/concerns → lib}/search_extension.rb +0 -0
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: false
2
2
 
3
3
  # Copyright 2011-2013 innoQ Deutschland GmbH
4
4
  #
@@ -120,7 +120,7 @@ module ConceptsHelper
120
120
  render(association_class.partial_name(concept), further_options.merge(concept: concept, klass: association_class))
121
121
  end
122
122
  end
123
- html = render partial: '/partials/match/panel', locals: { body: matches_html, klass: Match::SKOS::Base }
123
+ html = render partial: '/partials/match/panel', locals: { body: matches_html, klass: Match::Skos::Base }
124
124
  if String.new(html).squish.present?
125
125
  ((hash[association_classes.first.view_section(concept)] ||= {})[association_classes.first.view_section_sort_key(concept)] ||= '') << html.html_safe
126
126
  end
@@ -83,9 +83,9 @@ module NavigationHelper
83
83
 
84
84
  def nav_item(item)
85
85
  active = item[:active?] ? instance_eval(&item[:active?]) : (item[:controller] ? params[:controller] == item[:controller] : false)
86
- css = 'nav-item'
87
- css << ' active' if active
88
- content_tag :li, class: css do
86
+ css = ['nav-item']
87
+ css << 'active' if active
88
+ content_tag :li, class: css.join(' ') do
89
89
  nav_link(item)
90
90
  end
91
91
  end
@@ -93,12 +93,12 @@ module NavigationHelper
93
93
  def nav_link(item, opts = {})
94
94
  active = item[:active?] ? instance_eval(&item[:active?]) : (item[:controller] ? params[:controller] == item[:controller] : false)
95
95
 
96
- css = opts[:class] || 'nav-link'
97
- css << ' active' if active
98
- css << ' dropdown-toggle' if opts[:has_children]
96
+ css = [ opts[:class] || 'nav-link' ]
97
+ css << 'active' if active
98
+ css << 'dropdown-toggle' if opts[:has_children]
99
99
 
100
100
  link_opts = {
101
- class: css
101
+ class: css.join(' ')
102
102
  }
103
103
 
104
104
  dropdown_opts = {
@@ -90,6 +90,8 @@ module RdfHelper
90
90
  end
91
91
 
92
92
  document << collection.build_rdf_subject do |c|
93
+ c.Schema::expires(collection.expired_at.to_s) if collection.expired_at
94
+ c.Owl::deprecated(true) if collection.expired?
93
95
 
94
96
  collection.labelings.each do |labeling|
95
97
  labeling.build_rdf(document, c)
@@ -7,18 +7,15 @@ class ExportJob < Struct.new(:export, :filename, :type, :base_uri)
7
7
  end
8
8
 
9
9
  def perform
10
- strio = StringIO.new
11
-
12
- exporter = SkosExporter.new(filename, type, base_uri, Logger.new(strio))
10
+ exporter = SkosExporter.new(filename, type, base_uri, EntityLogger.new(export))
13
11
  exporter.run
14
- @messages = strio.string
15
12
  end
16
13
 
17
- def success(job)
18
- export.finish!(@messages)
14
+ def success(_job)
15
+ export.finish!
19
16
  end
20
17
 
21
- def error(job, exception)
18
+ def error(_job, exception)
22
19
  export.fail!(exception)
23
20
  end
24
21
  end
@@ -20,12 +20,6 @@ class Collection::Base < Concept::Base
20
20
  include mod
21
21
  end
22
22
 
23
- has_many Note::SKOS::Definition.name.to_relation_name,
24
- class_name: 'Note::SKOS::Definition',
25
- as: :owner,
26
- dependent: :destroy,
27
- inverse_of: :owner
28
-
29
23
  has_many :members,
30
24
  class_name: 'Collection::Member::Base',
31
25
  foreign_key: 'collection_id',
@@ -43,12 +37,12 @@ class Collection::Base < Concept::Base
43
37
  source: 'collection'
44
38
 
45
39
  has_many :concepts,
46
- -> { where("concepts.type = ?", Iqvoc::Concept.base_class) },
40
+ -> { where("concepts.type = ?", Iqvoc::Concept.base_class.name) },
47
41
  through: :members,
48
42
  source: :target
49
43
 
50
44
  has_many :subcollections,
51
- -> { where("concepts.type = ?", Iqvoc::Collection.base_class) },
45
+ -> { where("concepts.type = ?", Iqvoc::Collection.base_class.name) },
52
46
  through: :members,
53
47
  source: :target
54
48
 
@@ -96,6 +90,10 @@ class Collection::Base < Concept::Base
96
90
  'collection_dashboard_path'
97
91
  end
98
92
 
93
+ def self.inline_partial_name
94
+ 'partials/collection/inline_base'
95
+ end
96
+
99
97
  def self.edit_link_partial_name
100
98
  'partials/collection/edit_link_base'
101
99
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Collection::Member::SKOS::Base < Collection::Member::Base
17
+ class Collection::Member::Skos::Base < Collection::Member::Base
18
18
  self.rdf_namespace = 'skos'
19
19
  self.rdf_predicate = 'member'
20
20
 
@@ -24,7 +24,7 @@ class Collection::Member::SKOS::Base < Collection::Member::Base
24
24
 
25
25
  member_instance = rdf_subject.members.detect{ |rel| rel.target == rdf_object }
26
26
  if member_instance.nil?
27
- predicate_class = RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
27
+ predicate_class = RdfApi::PREDICATE_DICTIONARY[rdf_predicate] || self
28
28
  member_instance = predicate_class.new(target: rdf_object)
29
29
  rdf_subject.members << member_instance
30
30
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Collection::SKOS::Base < Collection::Base
17
+ class Collection::Skos::Base < Collection::Base
18
18
  self.rdf_namespace = 'skos'
19
19
  self.rdf_class = 'Collection'
20
20
 
@@ -14,5 +14,5 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Collection::SKOS::Unordered < Collection::SKOS::Base
17
+ class Collection::Skos::Unordered < Collection::Skos::Base
18
18
  end
@@ -14,9 +14,9 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Collection::Unordered < Collection::SKOS::Base
17
+ class Collection::Unordered < Collection::Skos::Base
18
18
  def initialize(*args)
19
- ActiveSupport::Deprecation.warn('Collection::Unordered is deprecated. Use Collection::SKOS::Unordered instead.')
19
+ ActiveSupport::Deprecation.warn('Collection::Unordered is deprecated. Use Collection::Skos::Unordered instead.')
20
20
  super
21
21
  end
22
22
  end
@@ -33,6 +33,7 @@ class Concept::Base < ApplicationRecord
33
33
  include Concept::Validations
34
34
  include FirstLevelObjectValidations
35
35
  include FirstLevelObjectScopes
36
+ include Expirable
36
37
 
37
38
  # ********** Hooks
38
39
 
@@ -46,7 +47,7 @@ class Concept::Base < ApplicationRecord
46
47
  # Handle save or destruction of inline relations (relations or labelings)
47
48
  # for use with widgets etc.
48
49
 
49
- # Inline assigned SKOS::Labels
50
+ # Inline assigned Skos::Labels
50
51
  # @labelings_by_text # => {'relation_name' => {'lang' => 'label1, label2, ...'}}
51
52
  (@labelings_by_text ||= {}).each do |relation_name, lang_values|
52
53
  relation_name = relation_name.to_s
@@ -368,15 +369,6 @@ class Concept::Base < ApplicationRecord
368
369
 
369
370
  # ********** Scopes
370
371
 
371
- def self.expired(time = Time.now)
372
- where(arel_table[:expired_at].lteq(time))
373
- end
374
-
375
- def self.not_expired(time = Time.now)
376
- col = arel_table[:expired_at]
377
- where((col.eq(nil)).or(col.gt(time)))
378
- end
379
-
380
372
  def self.tops
381
373
  where(top_term: true)
382
374
  end
@@ -22,7 +22,7 @@ class Concept::Relation::Base < ApplicationRecord
22
22
  # So use Concept::Base ONLY in methods or procs.
23
23
  #
24
24
  # The reason for this lies in the fact that Concept::Base calls the
25
- # Concept::Relation::SKOS::Broader::Base.narrower_class method to create all
25
+ # Concept::Relation::Skos::Broader::Base.narrower_class method to create all
26
26
  # concept_relation relations. This means Concept::Base triggers Rails to load
27
27
  # the Concept::Relation::* classes. If this would trigger Rails to load
28
28
  # Concept::Base we would have a loop == a problem.
@@ -14,14 +14,14 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::Relation::SKOS::Base < Concept::Relation::Base
17
+ class Concept::Relation::Skos::Base < Concept::Relation::Base
18
18
  self.rdf_namespace = 'skos'
19
19
 
20
20
  def self.build_from_rdf(rdf_subject, rdf_predicate, rdf_object)
21
21
  raise "#{self.name}#build_from_rdf: Subject (#{rdf_subject}) must be a Concept." unless rdf_subject.is_a? Concept::Base
22
22
  raise "#{self.name}#build_from_rdf: Object (#{rdf_object}) must be a Concept." unless rdf_object.is_a? Concept::Base
23
23
 
24
- relation_class = RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
24
+ relation_class = RdfApi::PREDICATE_DICTIONARY[rdf_predicate] || self
25
25
 
26
26
  relation_instance = rdf_subject.send(self.name.to_relation_name).select{ |rel| rel.target == rdf_object }
27
27
  if relation_instance.empty?
@@ -14,11 +14,11 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::Relation::SKOS::Broader::Base < Concept::Relation::SKOS::Base
17
+ class Concept::Relation::Skos::Broader::Base < Concept::Relation::Skos::Base
18
18
  self.rdf_predicate = 'broader'
19
19
 
20
20
  def self.narrower_class
21
- Concept::Relation::SKOS::Narrower::Base
21
+ Concept::Relation::Skos::Narrower::Base
22
22
  end
23
23
 
24
24
  def self.reverse_relation_class
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::Relation::SKOS::Broader::Mono < Concept::Relation::SKOS::Broader::Base
17
+ class Concept::Relation::Skos::Broader::Mono < Concept::Relation::Skos::Broader::Base
18
18
  def self.partial_name(obj)
19
19
  'partials/concept/relation/skos/broader/mono'
20
20
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::Relation::SKOS::Broader::Poly < Concept::Relation::SKOS::Broader::Base
17
+ class Concept::Relation::Skos::Broader::Poly < Concept::Relation::Skos::Broader::Base
18
18
  def self.partial_name(obj)
19
19
  'partials/concept/relation/skos/broader/poly'
20
20
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::Relation::SKOS::Narrower::Base < Concept::Relation::SKOS::Base
17
+ class Concept::Relation::Skos::Narrower::Base < Concept::Relation::Skos::Base
18
18
  self.rdf_predicate = 'narrower'
19
19
 
20
20
  def self.reverse_relation_class
@@ -14,6 +14,6 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::Relation::SKOS::Related < Concept::Relation::SKOS::Base
17
+ class Concept::Relation::Skos::Related < Concept::Relation::Skos::Base
18
18
  self.rdf_predicate = 'related'
19
19
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::SKOS::Base < Concept::Base
17
+ class Concept::Skos::Base < Concept::Base
18
18
  self.rdf_namespace = 'skos'
19
19
  self.rdf_class = 'Concept'
20
20
 
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Concept::SKOS::Scheme < Concept::Base
17
+ class Concept::Skos::Scheme < Concept::Base
18
18
  private_class_method :new
19
19
 
20
20
  after_update :redeclare_top_concepts
@@ -87,7 +87,7 @@ class Concept::SKOS::Scheme < Concept::Base
87
87
 
88
88
  def mono_hierarchy?
89
89
  Iqvoc::Concept.broader_relation_class.new.kind_of?(
90
- Concept::Relation::SKOS::Broader::Mono
90
+ Concept::Relation::Skos::Broader::Mono
91
91
  )
92
92
  end
93
93
 
@@ -12,6 +12,7 @@ module Concept
12
12
  validate :valid_rank_for_ranked_relations
13
13
  validate :unique_pref_labels
14
14
  validate :exclusive_pref_and_alt_labels_per_concept
15
+ validate :exclusive_hidden_labels_per_concept
15
16
  validate :unique_alt_labels
16
17
  validate :exclusive_broader_and_narrower_concepts
17
18
  validate :no_self_reference_concept_relation
@@ -101,6 +102,19 @@ module Concept
101
102
  end
102
103
  end
103
104
 
105
+ def exclusive_hidden_labels_per_concept
106
+ if self.validatable_for_publishing?
107
+ relevant_labels = self.labelings.reject { |lbl| lbl.is_a?(Iqvoc::Concept.hidden_labeling_class) }.collect(&:target)
108
+
109
+ self.hidden_labels.each do |hidden_label|
110
+ if relevant_labels.include? hidden_label
111
+ errors.add :base, I18n.t('txt.models.concept.hidden_label_defined_in_other_labels', label: hidden_label.value)
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
104
118
  def unique_alt_labels
105
119
  if validatable_for_publishing?
106
120
  alt_labels = alt_labelings.collect { |l| l.target }
@@ -0,0 +1,14 @@
1
+ module Expirable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ def self.expired(time = Time.now)
6
+ where(arel_table[:expired_at].lteq(time))
7
+ end
8
+
9
+ def self.not_expired(time = Time.now)
10
+ col = arel_table[:expired_at]
11
+ where((col.eq(nil)).or(col.gt(time)))
12
+ end
13
+ end
14
+ end
data/app/models/export.rb CHANGED
@@ -1,32 +1,44 @@
1
1
  class Export < ApplicationRecord
2
2
  belongs_to :user
3
3
 
4
- enum file_type: [:ttl, :nt, :xml]
4
+ enum :file_type, [:ttl, :nt, :xml]
5
5
 
6
6
  validates_presence_of :default_namespace
7
7
 
8
- before_destroy :delete_dump_file
8
+ before_destroy do
9
+ self.delete_dump_file
10
+ self.jobs.destroy_all
11
+ end
9
12
 
10
- def finish!(messages)
11
- self.output = messages
13
+ def finish!
12
14
  self.success = true
13
15
  self.finished_at = Time.now
14
- save!
16
+ self.save!
15
17
  end
16
18
 
17
19
  def fail!(exception)
18
- self.output = exception.to_s + "\n\n" + exception.backtrace.join("\n")
20
+ self.output += exception.to_s + "\n\n" + exception.backtrace.join("\n")
19
21
  self.finished_at = Time.now
20
- save!
22
+ self.save!
21
23
  end
22
24
 
23
25
  def build_filename
24
- File.join(Iqvoc.export_path, "#{token}.#{file_type}")
26
+ File.join(Iqvoc.export_path, "#{self.token}.#{self.file_type}")
27
+ end
28
+
29
+ def jobs
30
+ Rails.logger.debug "Deleting jobs for export #{self.id} (#{self.to_global_id})"
31
+ Delayed::Backend::ActiveRecord::Job.where(delayed_global_reference_id: self.to_global_id.to_s)
25
32
  end
26
33
 
27
34
  private
28
35
 
29
36
  def delete_dump_file
30
- File.delete(build_filename) if File.exist?(build_filename)
37
+ if File.exist?(self.build_filename)
38
+ Rails.logger.debug "Deleting export file #{self.build_filename}"
39
+ File.delete(self.build_filename)
40
+ else
41
+ Rails.logger.debug "Export file #{self.build_filename} does not exist, cannot delete."
42
+ end
31
43
  end
32
44
  end
@@ -46,6 +46,24 @@ class Label::Base < ApplicationRecord
46
46
  through: :alt_labelings,
47
47
  source: :owner
48
48
 
49
+ has_many :collection_pref_labelings,
50
+ foreign_key: 'target_id',
51
+ class_name: Iqvoc::Collection.pref_labeling_class_name,
52
+ inverse_of: :target
53
+
54
+ has_many :pref_labeled_collections,
55
+ through: :collection_pref_labelings,
56
+ source: :owner
57
+
58
+ has_many :collection_alt_labelings,
59
+ foreign_key: 'target_id',
60
+ class_name: Iqvoc::Collection.alt_labeling_class_name,
61
+ inverse_of: :target
62
+
63
+ has_many :alt_labeled_collections,
64
+ through: :collection_alt_labelings,
65
+ source: :owner
66
+
49
67
  # ********* Scopes
50
68
 
51
69
  def self.by_language(lang_code)
@@ -82,7 +100,7 @@ class Label::Base < ApplicationRecord
82
100
  end
83
101
 
84
102
  def self.by_query_value(query)
85
- where(["#{table_name}.value ILIKE ?", query.mb_chars.downcase.to_s])
103
+ where(["#{table_name}.value ILIKE ?", query.to_s.downcase])
86
104
  end
87
105
 
88
106
  # Attention: This means that even label classes without version controll will also
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Label::SKOS::Base < Label::Base
17
+ class Label::Skos::Base < Label::Base
18
18
  after_initialize :publish
19
19
 
20
20
  validates :value, presence: { message: I18n.t('txt.models.label.value_error') }
@@ -48,6 +48,18 @@ class Labeling::Base < ApplicationRecord
48
48
  includes(:owner).merge(Iqvoc::Concept.base_class.not_expired)
49
49
  end
50
50
 
51
+ def self.collection_published
52
+ includes(:owner).merge(Collection::Base.published)
53
+ end
54
+
55
+ def self.collection_expired
56
+ includes(:owner).merge(Iqvoc::Collection.base_class.expired)
57
+ end
58
+
59
+ def self.collection_not_expired
60
+ includes(:owner).merge(Iqvoc::Collection.base_class.not_expired)
61
+ end
62
+
51
63
  def self.label_published
52
64
  includes(:target).merge(Label::Base.published)
53
65
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Labeling::SKOS::AltLabel < Labeling::SKOS::Base
17
+ class Labeling::Skos::AltLabel < Labeling::Skos::Base
18
18
  self.rdf_predicate = 'altLabel'
19
19
 
20
20
  def self.view_section_sort_key(obj)
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Labeling::SKOS::Base < Labeling::Base
17
+ class Labeling::Skos::Base < Labeling::Base
18
18
  self.rdf_namespace = 'skos'
19
19
 
20
20
  # ********** Associations
@@ -63,7 +63,7 @@ class Labeling::SKOS::Base < Labeling::Base
63
63
  scope = scope.where("#{Collection::Member::Base.table_name}.collection_id" => collection.id)
64
64
  scope = scope.references(:collection_members)
65
65
  else
66
- raise "Collection with Origin #{params[:collection_origin]} not found!"
66
+ Rails.logger.warn "Collection with Origin #{params[:collection_origin]} not found!"
67
67
  end
68
68
  end
69
69
  scope = scope.includes(:owner)
@@ -136,7 +136,7 @@ class Labeling::SKOS::Base < Labeling::Base
136
136
  raise "#{self.name}#build_from_rdf: Subject (#{rdf_subject}) must be a Concept."
137
137
  end
138
138
 
139
- unless rdf_object =~ RDFAPI::LITERAL_REGEXP
139
+ unless rdf_object =~ RdfApi::LITERAL_REGEXP
140
140
  raise InvalidStringLiteralError, "#{self.name}#build_from_rdf: Object (#{rdf_object}) must be a string literal"
141
141
  end
142
142
 
@@ -147,7 +147,7 @@ class Labeling::SKOS::Base < Labeling::Base
147
147
  $1
148
148
  end
149
149
 
150
- predicate_class = RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
150
+ predicate_class = RdfApi::PREDICATE_DICTIONARY[rdf_predicate] || self
151
151
  predicate_class.new(target: self.label_class.new(value: value, language: lang)).tap do |labeling|
152
152
  rdf_subject.send(predicate_class.name.to_relation_name) << labeling
153
153
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Labeling::SKOS::HiddenLabel < Labeling::SKOS::Base
17
+ class Labeling::Skos::HiddenLabel < Labeling::Skos::Base
18
18
  self.rdf_predicate = 'hiddenLabel'
19
19
 
20
20
  def self.view_section_sort_key(obj)
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Labeling::SKOS::PrefLabel < Labeling::SKOS::Base
17
+ class Labeling::Skos::PrefLabel < Labeling::Skos::Base
18
18
  self.rdf_predicate = 'prefLabel'
19
19
 
20
20
  # if `singular` is true, only a single occurrence is allowed per instance
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::Base < Match::Base
17
+ class Match::Skos::Base < Match::Base
18
18
  self.rdf_namespace = 'skos'
19
19
 
20
20
  def self.build_from_rdf(rdf_subject, rdf_predicate, rdf_object)
@@ -22,14 +22,14 @@ class Match::SKOS::Base < Match::Base
22
22
  raise "#{self.class}#build_from_rdf: Object (#{rdf_object}) must be a URI" unless rdf_object =~ /^<(.+)>$/ # XXX: this assumes nt-format, right?
23
23
  uri = $1
24
24
 
25
- match_class = RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
25
+ match_class = RdfApi::PREDICATE_DICTIONARY[rdf_predicate] || self
26
26
  match_class.new(value: uri).tap do |match|
27
27
  rdf_subject.send(self.name.to_relation_name) << match
28
28
  end
29
29
  end
30
30
 
31
31
  def build_rdf(document, subject)
32
- raise "Match::SKOS::Base#build_rdf: Class #{self.name} needs to define self.rdf_namespace and self.rdf_predicate." unless self.rdf_namespace && self.rdf_predicate
32
+ raise "Match::Skos::Base#build_rdf: Class #{self.name} needs to define self.rdf_namespace and self.rdf_predicate." unless self.rdf_namespace && self.rdf_predicate
33
33
 
34
34
  if (IqRdf::Namespace.find_namespace_class(self.rdf_namespace.camelcase))
35
35
  subject.send(self.rdf_namespace.camelcase).send(self.rdf_predicate, URI.parse(value))
@@ -14,9 +14,9 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::BroadMatch < Match::SKOS::MappingRelation
17
+ class Match::Skos::BroadMatch < Match::Skos::MappingRelation
18
18
  def self.reverse_match_class_name
19
- 'Match::SKOS::NarrowMatch'
19
+ 'Match::Skos::NarrowMatch'
20
20
  end
21
21
 
22
22
  self.rdf_predicate = 'broadMatch'
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::CloseMatch < Match::SKOS::MappingRelation
17
+ class Match::Skos::CloseMatch < Match::Skos::MappingRelation
18
18
  def self.reverse_match_class_name
19
19
  self.to_s
20
20
  end
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::ExactMatch < Match::SKOS::MappingRelation
17
+ class Match::Skos::ExactMatch < Match::Skos::MappingRelation
18
18
  def self.reverse_match_class_name
19
19
  self.to_s
20
20
  end
@@ -14,6 +14,6 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::MappingRelation < Match::SKOS::Base
17
+ class Match::Skos::MappingRelation < Match::Skos::Base
18
18
  self.rdf_predicate = 'mappingRelation'
19
19
  end
@@ -14,9 +14,9 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::NarrowMatch < Match::SKOS::MappingRelation
17
+ class Match::Skos::NarrowMatch < Match::Skos::MappingRelation
18
18
  def self.reverse_match_class_name
19
- 'Match::SKOS::BroadMatch'
19
+ 'Match::Skos::BroadMatch'
20
20
  end
21
21
 
22
22
  self.rdf_predicate = 'narrowMatch'
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Match::SKOS::RelatedMatch < Match::SKOS::MappingRelation
17
+ class Match::Skos::RelatedMatch < Match::Skos::MappingRelation
18
18
  def self.reverse_match_class_name
19
19
  self.to_s
20
20
  end
@@ -73,7 +73,7 @@ class Note::Base < ApplicationRecord
73
73
  end
74
74
 
75
75
  def self.by_query_value(query)
76
- where(["#{table_name}.value ILIKE ?", query.mb_chars.downcase.to_s])
76
+ where(["#{table_name}.value ILIKE ?", query.to_s.downcase])
77
77
  end
78
78
 
79
79
  def self.by_owner_type(klass)
@@ -168,7 +168,7 @@ class Note::Base < ApplicationRecord
168
168
  scope = scope.where("#{Collection::Member::Base.table_name}.collection_id" => collection.id)
169
169
  scope = scope.references(:collection_members)
170
170
  else
171
- raise "Collection with Origin #{params[:collection_origin]} not found!"
171
+ Rails.logger.warn "Collection with Origin #{params[:collection_origin]} not found!"
172
172
  end
173
173
  end
174
174