iqvoc 4.7.0 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Gemfile +11 -11
  4. data/Gemfile.lock +178 -122
  5. data/README.md +39 -24
  6. data/{test/performance/browsing_test.rb → app/aides/inline_data_helper.rb} +23 -6
  7. data/app/aides/maker.rb +139 -0
  8. data/{lib → app/aides}/multi_logger.rb +0 -0
  9. data/app/aides/origin.rb +47 -0
  10. data/app/aides/rdfapi.rb +59 -0
  11. data/app/aides/skos_exporter.rb +151 -0
  12. data/app/aides/skos_importer.rb +348 -0
  13. data/app/assets/javascripts/iqvoc/entityselect.js.erb +7 -9
  14. data/app/controllers/application_controller.rb +1 -3
  15. data/app/controllers/collections/versions_controller.rb +1 -3
  16. data/app/controllers/concepts/versions_controller.rb +9 -3
  17. data/app/controllers/concerns/controller_extensions.rb +109 -0
  18. data/app/{concerns → controllers/concerns}/reverse_match_errors.rb +0 -0
  19. data/app/controllers/hierarchy_controller.rb +7 -3
  20. data/app/controllers/instance_configuration_controller.rb +1 -1
  21. data/app/controllers/pages_controller.rb +10 -0
  22. data/app/controllers/search_results_controller.rb +2 -2
  23. data/app/controllers/triplestore_sync_controller.rb +2 -4
  24. data/app/helpers/application_helper.rb +1 -1
  25. data/app/helpers/widget_helper.rb +3 -3
  26. data/app/jobs/export_job.rb +1 -3
  27. data/app/jobs/import_job.rb +1 -3
  28. data/app/models/ability.rb +59 -0
  29. data/app/models/abstract_user.rb +1 -1
  30. data/app/models/collection/base.rb +12 -3
  31. data/app/models/collection/member/skos/base.rb +1 -1
  32. data/app/models/concept/base.rb +15 -8
  33. data/app/models/concept/relation/base.rb +1 -1
  34. data/app/models/concept/relation/skos/base.rb +1 -1
  35. data/app/models/concept/skos/scheme.rb +1 -1
  36. data/app/models/concept/validations.rb +1 -1
  37. data/app/models/concerns/deep_cloning.rb +92 -0
  38. data/app/models/concerns/first_level_object_scopes.rb +9 -0
  39. data/app/{concerns → models/concerns}/first_level_object_validations.rb +9 -2
  40. data/app/models/concerns/rankable.rb +31 -0
  41. data/app/models/{search_extension.rb → concerns/search_extension.rb} +0 -0
  42. data/app/{concerns → models/concerns}/versioning.rb +0 -6
  43. data/app/models/configuration_setting.rb +1 -1
  44. data/app/models/labeling/skos/base.rb +2 -2
  45. data/app/models/match/skos/base.rb +2 -2
  46. data/app/models/note/skos/base.rb +7 -6
  47. data/app/models/note/skos/change_note.rb +1 -1
  48. data/{lib/iqvoc/rdf_sync.rb → app/services/rdf_sync_service.rb} +3 -3
  49. data/app/view_models/concept_view.rb +1 -1
  50. data/app/views/collections/_form.html.erb +2 -2
  51. data/app/views/concepts/scheme/edit.html.erb +1 -1
  52. data/app/views/pages/components.html.erb +45 -0
  53. data/app/views/pages/version.html.erb +6 -0
  54. data/app/views/partials/concept/_reverse_match_notice.html.erb +0 -1
  55. data/app/views/search_results/_sidebar.html.erb +3 -3
  56. data/config/application.rb +4 -1
  57. data/config/boot.rb +1 -2
  58. data/config/database.yml.postgresql +23 -0
  59. data/config/engine.rb +0 -2
  60. data/config/environments/heroku.rb +1 -1
  61. data/config/initializers/inflections.rb +9 -3
  62. data/config/initializers/iqvoc.rb +1 -7
  63. data/config/initializers/mime_types.rb +0 -1
  64. data/config/locales/de.yml +2 -1
  65. data/config/locales/en.yml +11 -10
  66. data/config/routes.rb +2 -0
  67. data/config/travis/database.yml.mysql +9 -0
  68. data/config/travis/database.yml.postgresql +7 -0
  69. data/config/travis/database.yml.sqlite +5 -0
  70. data/db/migrate/20141204151558_add_foreign_key_constraints.rb +23 -0
  71. data/iqvoc.gemspec +2 -2
  72. data/lib/generators/app/template.rb +15 -7
  73. data/lib/iqvoc.rb +2 -1
  74. data/lib/iqvoc/configuration/core.rb +18 -4
  75. data/lib/iqvoc/configuration/instance_configuration.rb +125 -0
  76. data/lib/iqvoc/configuration/navigation.rb +63 -0
  77. data/lib/iqvoc/environments/development.rb +4 -0
  78. data/lib/iqvoc/environments/production.rb +11 -12
  79. data/lib/iqvoc/environments/test.rb +4 -1
  80. data/lib/iqvoc/version.rb +2 -2
  81. data/lib/tasks/exporter.rake +1 -4
  82. data/lib/tasks/importer.rake +1 -5
  83. data/lib/tasks/sync.rake +1 -2
  84. data/test/controllers/concept_movement_test.rb +11 -11
  85. data/test/controllers/hierarchy_test.rb +83 -79
  86. data/test/controllers/reverse_match_test.rb +2 -2
  87. data/test/integration/alphabetical_test.rb +2 -3
  88. data/test/integration/browse_concepts_and_labels_test.rb +2 -2
  89. data/test/integration/collection_circularity_test.rb +6 -6
  90. data/test/integration/concept_scheme_browsing_test.rb +2 -2
  91. data/test/integration/edit_concepts_test.rb +1 -1
  92. data/test/integration/export_test.rb +5 -3
  93. data/test/integration/import_test.rb +4 -1
  94. data/test/integration/instance_configuration_browsing_test.rb +2 -2
  95. data/test/integration/navigation_test.rb +2 -2
  96. data/test/integration/note_annotations_test.rb +12 -11
  97. data/test/integration/reverse_match_job_test.rb +19 -10
  98. data/test/integration/search_test.rb +6 -6
  99. data/test/integration/tree_test.rb +3 -3
  100. data/test/integration/untranslated_test.rb +1 -1
  101. data/test/models/concept_test.rb +13 -14
  102. data/test/models/inline_data_test.rb +9 -9
  103. data/test/models/instance_configuration_test.rb +7 -3
  104. data/test/models/origin_test.rb +9 -59
  105. data/test/models/rdf_sync_test.rb +2 -4
  106. data/test/models/rdfapi_test.rb +0 -2
  107. data/test/models/skos_collection_import_test.rb +3 -4
  108. data/test/models/skos_export_test.rb +3 -5
  109. data/test/models/skos_import_test.rb +12 -10
  110. data/test/test_helper.rb +0 -1
  111. data/vendor/assets/stylesheets/{jquery-ui.css.scss → jquery-ui.scss} +0 -0
  112. data/vendor/assets/stylesheets/{jquery-ui.structure.css.scss → jquery-ui.structure.scss} +0 -0
  113. data/vendor/assets/stylesheets/{jquery-ui.theme.css.scss → jquery-ui.theme.scss} +0 -0
  114. metadata +34 -28
  115. data/lib/iqvoc/ability.rb +0 -60
  116. data/lib/iqvoc/controller_extensions.rb +0 -111
  117. data/lib/iqvoc/deep_cloning.rb +0 -90
  118. data/lib/iqvoc/inline_data_helper.rb +0 -45
  119. data/lib/iqvoc/instance_configuration.rb +0 -123
  120. data/lib/iqvoc/maker.rb +0 -141
  121. data/lib/iqvoc/navigation.rb +0 -61
  122. data/lib/iqvoc/origin.rb +0 -111
  123. data/lib/iqvoc/rankable.rb +0 -33
  124. data/lib/iqvoc/rdfapi.rb +0 -60
  125. data/lib/iqvoc/skos_exporter.rb +0 -153
  126. data/lib/iqvoc/skos_importer.rb +0 -337
@@ -113,6 +113,7 @@ class HierarchyController < ApplicationController
113
113
 
114
114
  scope = Iqvoc::Concept.base_class
115
115
  scope = include_unpublished ? scope.editor_selectable : scope.published
116
+ scope = scope.ordered_by_pref_label
116
117
 
117
118
  # validate depth parameter
118
119
  if not depth
@@ -176,7 +177,8 @@ class HierarchyController < ApplicationController
176
177
 
177
178
  rels = scope.where(Concept::Relation::Base.arel_table[:target_id].
178
179
  eq(root_concept.id)).references(:concept_relations)
179
- return rels.inject({}) do |memo, concept|
180
+
181
+ results = rels.inject({}) do |memo, concept|
180
182
  if include_siblings
181
183
  determine_siblings(concept).each { |sib| memo[sib] = {} }
182
184
  end
@@ -184,12 +186,14 @@ class HierarchyController < ApplicationController
184
186
  current_depth, include_siblings)
185
187
  memo
186
188
  end
189
+
190
+ results
187
191
  end
188
192
 
189
193
  # NB: includes support for poly-hierarchies -- XXX: untested
190
194
  def determine_siblings(concept)
191
- return concept.broader_relations.map do |rel|
195
+ concept.broader_relations.map do |rel|
192
196
  rel.target.narrower_relations.map { |rel| rel.target } # XXX: expensive
193
- end.flatten.uniq
197
+ end.flatten.uniq.sort { |a, b| a.pref_label <=> b.pref_label }
194
198
  end
195
199
  end
@@ -69,7 +69,7 @@ class InstanceConfigurationController < ApplicationController
69
69
 
70
70
  # default value determines value type
71
71
  def serialize(value, default_value)
72
- Iqvoc::InstanceConfiguration.validate_value(value)
72
+ Iqvoc::Configuration::InstanceConfiguration.validate_value(value)
73
73
  if default_value.is_a?(Array)
74
74
  return value.to_csv.strip
75
75
  else # boolean, String, Fixnum / Float
@@ -15,7 +15,17 @@
15
15
  # limitations under the License.
16
16
 
17
17
  class PagesController < ApplicationController
18
+ def components
19
+ #authorize! :read, :components
20
+ @concepts_uri = concepts_path(:format => :json)
21
+ @concept_uri = concept_path(:id => "{id}")
22
+ end
23
+
18
24
  def help
19
25
  authorize! :read, :help
20
26
  end
27
+
28
+ def version
29
+ authorize! :read, :version
30
+ end
21
31
  end
@@ -113,13 +113,13 @@ class SearchResultsController < ApplicationController
113
113
 
114
114
  if klass.forces_multi_query? || (klass.supports_multi_query? && query_size > 1)
115
115
  @multi_query = true
116
- @results = klass.multi_query(params.merge({ languages: languages }))
116
+ @results = klass.multi_query(params.merge({ languages: languages.flatten }))
117
117
  # TODO: Add a worst case limit here; e.g. when on page 2 (per_page == 50)
118
118
  # each sub-query has to return 100 objects at most.
119
119
  @klass = klass
120
120
  else
121
121
  @multi_query = false
122
- @results = klass.single_query(params.merge({ languages: languages }))
122
+ @results = klass.single_query(params.merge({ languages: languages.flatten }))
123
123
  end
124
124
 
125
125
  if @multi_query
@@ -14,10 +14,8 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'iqvoc/rdf_sync'
18
-
19
17
  class TriplestoreSyncController < ApplicationController
20
- include Iqvoc::RDFSync::Helper
18
+ include RDFSyncService::Helper
21
19
 
22
20
  def index
23
21
  authorize! :use, :dashboard
@@ -42,7 +40,7 @@ class TriplestoreSyncController < ApplicationController
42
40
  end
43
41
 
44
42
  # per-class pagination
45
- @candidates = Iqvoc::RDFSync.candidates.map do |records|
43
+ @candidates = RDFSyncService.candidates.map do |records|
46
44
  records.page(params[:page])
47
45
  end
48
46
  end
@@ -56,7 +56,7 @@ module ApplicationHelper
56
56
 
57
57
  def page_header(args = {})
58
58
  if title = args[:title]
59
- content_for(:title, title)
59
+ content_for(:title, strip_tags(title))
60
60
  end
61
61
 
62
62
  content_for :page_header do
@@ -5,13 +5,13 @@ module WidgetHelper
5
5
 
6
6
  def widget_values_ranked(concept, relation_class)
7
7
  concepts_with_ranks = concept.concept_relations_by_id_and_rank(relation_class.name.to_relation_name)
8
- concepts_with_ranks.map { |concept, rank| "#{concept.origin}:#{rank}" }.join(Iqvoc::InlineDataHelper::JOINER)
8
+ concepts_with_ranks.map { |concept, rank| "#{concept.origin}:#{rank}" }.join(InlineDataHelper::JOINER)
9
9
  end
10
10
 
11
11
  def widget_entities(concept, relation_class)
12
12
  origins = concept.
13
13
  concept_relations_by_id(relation_class.name.to_relation_name).
14
- split(Iqvoc::InlineDataHelper::SPLITTER)
14
+ split(InlineDataHelper::SPLITTER)
15
15
 
16
16
  Iqvoc::Concept.base_class.
17
17
  editor_selectable.
@@ -23,7 +23,7 @@ module WidgetHelper
23
23
  def widget_entities_ranked(concept, relation_class)
24
24
  origins = concept.
25
25
  concept_relations_by_id(relation_class.name.to_relation_name).
26
- split(Iqvoc::InlineDataHelper::SPLITTER)
26
+ split(InlineDataHelper::SPLITTER)
27
27
 
28
28
  allowed_concepts = Iqvoc::Concept.base_class.
29
29
  editor_selectable.
@@ -1,10 +1,8 @@
1
- require 'iqvoc/skos_exporter'
2
-
3
1
  class ExportJob < Struct.new(:export, :filename, :type, :base_uri)
4
2
  def perform
5
3
  strio = StringIO.new
6
4
 
7
- exporter = Iqvoc::SkosExporter.new(filename, type, base_uri, Logger.new(strio))
5
+ exporter = SkosExporter.new(filename, type, base_uri, Logger.new(strio))
8
6
  exporter.run
9
7
  @messages = strio.string
10
8
  end
@@ -1,10 +1,8 @@
1
- require 'iqvoc/skos_importer'
2
-
3
1
  class ImportJob < Struct.new(:import, :filename, :user, :namespace, :publish)
4
2
  def perform
5
3
  strio = StringIO.new
6
4
 
7
- importer = Iqvoc::SkosImporter.new(filename, namespace, Logger.new(strio), publish)
5
+ importer = SkosImporter.new(filename, namespace, Logger.new(strio), publish)
8
6
  importer.run
9
7
  @messages = strio.string
10
8
  end
@@ -0,0 +1,59 @@
1
+ class Ability
2
+ include CanCan::Ability
3
+
4
+ @@if_published = lambda { |o| o.published? }
5
+
6
+ def initialize(user = nil)
7
+ can :read, Iqvoc::Concept.root_class.instance
8
+ can :read, [::Concept::Base, ::Collection::Base, ::Label::Base], &@@if_published
9
+
10
+ # static pages
11
+ can :read, :help
12
+ can :read, :version
13
+
14
+ if user # Every logged in user ...
15
+ can :use, :dashboard
16
+ can :destroy, UserSession
17
+
18
+ if user.owns_role?(:editor) || user.owns_role?(:publisher) || user.owns_role?(:administrator) # Editors and above ...
19
+ can :read, [::Concept::Base, ::Collection::Base, ::Label::Base]
20
+ can :create, [::Concept::Base, ::Collection::Base, ::Label::Base]
21
+ can [:update, :destroy, :unlock], [::Concept::Base, ::Collection::Base, ::Label::Base], locked_by: user.id, published_at: nil
22
+ can :lock, [::Concept::Base, ::Collection::Base, ::Label::Base], locked_by: nil, published_at: nil
23
+ can [:check_consistency, :send_to_review], [::Concept::Base, ::Collection::Base, ::Label::Base], published_at: nil
24
+ can :branch, [::Concept::Base, ::Collection::Base, ::Label::Base], &@@if_published
25
+ end
26
+
27
+ if user.owns_role?(:match_editor)
28
+ can :read, ::Concept::Base
29
+ can :create, ::Concept::Base
30
+ can [:update, :lock], ::Concept::Base, locked_by: user.id, published_at: nil
31
+ can :lock, ::Concept::Base, locked_by: nil, published_at: nil
32
+ can :branch, ::Concept::Base, &@@if_published
33
+ end
34
+
35
+ if user.owns_role?(:publisher) || user.owns_role?(:administrator) # Publishers and above ...
36
+ can :merge, [::Concept::Base, ::Collection::Base, ::Label::Base], published_at: nil
37
+ end
38
+
39
+ if user.owns_role?(:administrator)
40
+ can [:update, :destroy, :unlock], [::Concept::Base, ::Label::Base], published_at: nil # Mustn't be locked by myself
41
+
42
+ can :manage, User
43
+ can :manage, Iqvoc.config
44
+
45
+ can :full_export, ::Concept::Base
46
+ can :import, ::Concept::Base
47
+ can :export, ::Concept::Base
48
+
49
+ can :update, Iqvoc::Concept.root_class.instance
50
+
51
+ can :use, :administration
52
+
53
+ can :reset, :thesaurus
54
+ end
55
+ else # no user
56
+ can :create, UserSession
57
+ end
58
+ end
59
+ end
@@ -46,6 +46,6 @@ class AbstractUser < ActiveRecord::Base
46
46
  end
47
47
 
48
48
  def ability
49
- @ability ||= Iqvoc::Ability.new(self)
49
+ @ability ||= Ability.new(self)
50
50
  end
51
51
  end
@@ -34,7 +34,16 @@ class Collection::Base < Concept::Base
34
34
 
35
35
  include_to_deep_cloning(:members, :collection_members)
36
36
 
37
- after_save :regenerate_concept_members, :regenerate_collection_members
37
+ # ********** Hooks
38
+
39
+ after_initialize do |collection|
40
+ if collection.origin.blank?
41
+ collection.origin = Origin.new.to_s
42
+ end
43
+ end
44
+
45
+ after_save :regenerate_concept_members,
46
+ :regenerate_collection_members
38
47
 
39
48
  validate :circular_subcollections
40
49
 
@@ -90,7 +99,7 @@ class Collection::Base < Concept::Base
90
99
 
91
100
  def inline_member_concept_origins=(origins)
92
101
  @member_concept_origins = origins.to_s.
93
- split(Iqvoc::InlineDataHelper::SPLITTER).map(&:strip)
102
+ split(InlineDataHelper::SPLITTER).map(&:strip)
94
103
  end
95
104
 
96
105
  def inline_member_concept_origins
@@ -107,7 +116,7 @@ class Collection::Base < Concept::Base
107
116
 
108
117
  def inline_member_collection_origins=(origins)
109
118
  @member_collection_origins = origins.to_s.
110
- split(Iqvoc::InlineDataHelper::SPLITTER).map(&:strip)
119
+ split(InlineDataHelper::SPLITTER).map(&:strip)
111
120
  end
112
121
 
113
122
  def inline_member_collection_origins
@@ -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 = Iqvoc::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
@@ -32,9 +32,16 @@ class Concept::Base < ActiveRecord::Base
32
32
  include Versioning
33
33
  include Concept::Validations
34
34
  include FirstLevelObjectValidations
35
+ include FirstLevelObjectScopes
35
36
 
36
37
  # ********** Hooks
37
38
 
39
+ after_initialize do |concept|
40
+ if concept.origin.blank?
41
+ concept.origin = Origin.new.to_s
42
+ end
43
+ end
44
+
38
45
  before_validation do |concept|
39
46
  # Handle save or destruction of inline relations (relations or labelings)
40
47
  # for use with widgets etc.
@@ -50,7 +57,7 @@ class Concept::Base < ActiveRecord::Base
50
57
  lang_values = { nil => lang_values.first } if lang_values.is_a?(Array) # For language = nil: <input name=bla[labeling_class][]> => Results in an Array! -- XXX: obsolete/dupe (cf `labelings_by_text=`)?
51
58
  lang_values.each do |lang, inline_values|
52
59
  lang = nil if lang.to_s == 'none'
53
- Iqvoc::InlineDataHelper.parse_inline_values(inline_values).each do |value|
60
+ InlineDataHelper.parse_inline_values(inline_values).each do |value|
54
61
  value.squish!
55
62
  unless value.blank?
56
63
  self.send(relation_name).build(target: labeling_class.label_class.new(value: value, language: lang))
@@ -72,7 +79,7 @@ class Concept::Base < ActiveRecord::Base
72
79
  # rankable: {'relation_name' => ['origin1:100', 'origin2:90']}
73
80
  (@concept_relations_by_id ||= {}).each do |relation_name, new_origins|
74
81
  # Split comma-separated origins and clean up parameter strings
75
- new_origins = new_origins.split(Iqvoc::InlineDataHelper::SPLITTER).map(&:squish)
82
+ new_origins = new_origins.split(InlineDataHelper::SPLITTER).map(&:squish)
76
83
 
77
84
  # Extract embedded ranks (if any) from origin strings (e.g. "origin1:100")
78
85
  # => { 'origin1' => nil, 'origin2' => 90 }
@@ -184,7 +191,7 @@ class Concept::Base < ActiveRecord::Base
184
191
  unless Iqvoc::Concept.labeling_classes.keys.detect { |klass| labeling_class_name.constantize < klass }
185
192
  # When a Label has only one labeling (the "no skosxl" case) we'll have to
186
193
  # clone the label too.
187
- if labeling_class_name.constantize.reflections[:target].options[:dependent] == :destroy
194
+ if labeling_class_name.constantize.reflections['target'].options[:dependent] == :destroy
188
195
  include_to_deep_cloning(labeling_class_name.to_relation_name => :target)
189
196
  else
190
197
  include_to_deep_cloning(labeling_class_name.to_relation_name)
@@ -199,13 +206,13 @@ class Concept::Base < ActiveRecord::Base
199
206
  class_name: match_class_name,
200
207
  foreign_key: 'concept_id'
201
208
 
202
- # Serialized setters and getters (\r\n or , separated) -- TODO: use Iqvoc::InlineDataHelper?
209
+ # Serialized setters and getters (\r\n or , separated) -- TODO: use InlineDataHelper?
203
210
  define_method("inline_#{match_class_name.to_relation_name}".to_sym) do
204
- self.send(match_class_name.to_relation_name).map(&:value).join(Iqvoc::InlineDataHelper::JOINER)
211
+ self.send(match_class_name.to_relation_name).map(&:value).join(InlineDataHelper::JOINER)
205
212
  end
206
213
 
207
214
  define_method("inline_#{match_class_name.to_relation_name}=".to_sym) do |value|
208
- urls = value.split(Iqvoc::InlineDataHelper::SPLITTER).map(&:strip).reject(&:blank?)
215
+ urls = value.split(InlineDataHelper::SPLITTER).map(&:strip).reject(&:blank?)
209
216
  self.send(match_class_name.to_relation_name).each do |match|
210
217
  if (urls.include?(match.value))
211
218
  urls.delete(match.value) # We're done with that one
@@ -319,7 +326,7 @@ class Concept::Base < ActiveRecord::Base
319
326
  def labelings_by_text(relation_name, language)
320
327
  (@labelings_by_text && @labelings_by_text[relation_name] &&
321
328
  @labelings_by_text[relation_name][language]) ||
322
- Iqvoc::InlineDataHelper.generate_inline_values(self.send(relation_name).
329
+ InlineDataHelper.generate_inline_values(self.send(relation_name).
323
330
  by_label_language(language).map { |l| l.target.value })
324
331
  end
325
332
 
@@ -330,7 +337,7 @@ class Concept::Base < ActiveRecord::Base
330
337
  def concept_relations_by_id(relation_name)
331
338
  (@concept_relations_by_id && @concept_relations_by_id[relation_name]) ||
332
339
  self.send(relation_name).map { |l| l.target.origin }.
333
- join(Iqvoc::InlineDataHelper::JOINER)
340
+ join(InlineDataHelper::JOINER)
334
341
  end
335
342
 
336
343
  def concept_relations_by_id_and_rank(relation_name)
@@ -124,6 +124,6 @@ class Concept::Relation::Base < ActiveRecord::Base
124
124
  end
125
125
 
126
126
  def self.rankable?
127
- self.class.included_modules.include?(Iqvoc::Rankable)
127
+ self.class.included_modules.include?(Rankable)
128
128
  end
129
129
  end
@@ -21,7 +21,7 @@ class Concept::Relation::SKOS::Base < Concept::Relation::Base
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 = Iqvoc::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?
@@ -61,7 +61,7 @@ class Concept::SKOS::Scheme < Concept::Base
61
61
 
62
62
  def inline_top_concept_origins=(origins)
63
63
  @inline_top_concept_origins = origins.to_s.
64
- split(Iqvoc::InlineDataHelper::SPLITTER).map(&:strip)
64
+ split(InlineDataHelper::SPLITTER).map(&:strip)
65
65
  end
66
66
 
67
67
  def inline_top_concept_origins
@@ -16,7 +16,7 @@ module Concept
16
16
  # top term and broader relations are mutually exclusive
17
17
  def exclusive_top_term
18
18
  if validatable_for_publishing?
19
- if top_term && broader_relations.any?
19
+ if top_term? && broader_relations.any?
20
20
  errors.add :base, I18n.t('txt.models.concept.top_term_exclusive_error')
21
21
  end
22
22
  end
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2011-2013 innoQ Deutschland GmbH
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/concern'
18
+
19
+ module DeepCloning
20
+ extend ActiveSupport::Concern
21
+
22
+ included do #:nodoc:
23
+ alias_method_chain :dup, :deep_cloning
24
+ end
25
+
26
+ # clones an ActiveRecord model.
27
+ # if passed the :include option, it will deep clone the given associations
28
+ # if passed the :except option, it won't clone the given attributes
29
+ #
30
+ # === Usage:
31
+ #
32
+ # ==== Cloning a model without an attribute
33
+ # pirate.clone except: :name
34
+ #
35
+ # ==== Cloning a model without multiple attributes
36
+ # pirate.clone except: [:name, :nick_name]
37
+ # ==== Cloning one single association
38
+ # pirate.clone include: :mateys
39
+ #
40
+ # ==== Cloning multiple associations
41
+ # pirate.clone include: [:mateys, :treasures]
42
+ #
43
+ # ==== Cloning really deep
44
+ # pirate.clone include: {treasures: :gold_pieces}
45
+ #
46
+ # ==== Cloning really deep with multiple associations
47
+ # pirate.clone include: [:mateys, {treasures: :gold_pieces}]
48
+ #
49
+ # ==== Cloning multiple associations - but only the join table entries without cloning the associated objects themselves
50
+ # pirate.clone include_association: [:matey_ids, :treasure_ids]
51
+ #
52
+ def dup_with_deep_cloning(options = {})
53
+ kopy = dup_without_deep_cloning
54
+
55
+ if options[:except]
56
+ Array(options[:except]).each do |attribute|
57
+ kopy.write_attribute(attribute, attributes_from_column_definition[attribute.to_s])
58
+ end
59
+ end
60
+
61
+ if options[:include_association]
62
+ Array(options[:include_association]).each do |association_attribute|
63
+ kopy.send("#{association_attribute}=", self.send("#{association_attribute}"))
64
+ end
65
+ end
66
+
67
+ if options[:include]
68
+ Array(options[:include]).each do |association, deep_associations|
69
+ if (association.kind_of? Hash)
70
+ deep_associations = association[association.keys.first]
71
+ association = association.keys.first
72
+ end
73
+ opts = deep_associations.blank? ? {} : { include: deep_associations }
74
+ association_reflection = self.class.reflect_on_association(association)
75
+ cloned_object = case association_reflection.macro
76
+ when :belongs_to, :has_one
77
+ self.send(association) && self.send(association).dup(opts)
78
+ when :has_many, :has_and_belongs_to_many
79
+ fk = association_reflection.options[:foreign_key]# || self.class.to_s.underscore
80
+ self.send(association).collect do |obj|
81
+ cloned_obj = obj.dup(opts)
82
+ cloned_obj.send("#{fk}=", kopy.id) unless fk.blank?
83
+ cloned_obj
84
+ end
85
+ end
86
+ kopy.send("#{association}=", cloned_object)
87
+ end
88
+ end
89
+
90
+ return kopy
91
+ end
92
+ end