iqvoc 3.5.5 → 3.5.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/Gemfile +5 -7
- data/Gemfile.lock +52 -56
- data/app/assets/javascripts/iqvoc/iqvoc.js +9 -6
- data/app/controllers/rdf_controller.rb +1 -1
- data/app/helpers/rdf_helper.rb +1 -1
- data/app/models/collection/base.rb +6 -6
- data/app/models/concept/base.rb +15 -9
- data/app/models/concept/relation/base.rb +14 -14
- data/app/models/concept/skos/base.rb +10 -3
- data/app/models/concept/skos/scheme.rb +4 -4
- data/app/models/label/base.rb +27 -25
- data/app/models/labeling/base.rb +12 -12
- data/app/models/labeling/skos/base.rb +2 -2
- data/app/models/note/base.rb +15 -11
- data/app/views/partials/concept/relation/_edit_base.html.erb +2 -1
- data/config/database.yml +1 -4
- data/config/initializers/iqvoc.rb +1 -0
- data/config/initializers/secret_token.rb +1 -1
- data/config/routes.rb +1 -1
- data/lib/iqvoc/controller_extensions.rb +6 -3
- data/lib/iqvoc/environments/development.rb +35 -0
- data/lib/iqvoc/environments/production.rb +20 -0
- data/lib/{maker.rb → iqvoc/maker.rb} +1 -3
- data/lib/iqvoc/origin.rb +148 -0
- data/lib/iqvoc/skos_importer.rb +1 -1
- data/lib/iqvoc/version.rb +1 -1
- data/lib/iqvoc/versioning.rb +51 -53
- data/test/integration/concept_scheme_test.rb +3 -3
- data/test/integration/tree_test.rb +2 -2
- data/test/integration_test_helper.rb +30 -4
- data/test/unit/hygiene_test.rb +25 -0
- data/test/unit/origin_test.rb +75 -0
- metadata +27 -26
- data/app/models/origin_mapping.rb +0 -58
- data/config/deploy.rb +0 -72
- data/test/unit/origin_mapping_test.rb +0 -66
@@ -24,15 +24,15 @@ require 'singleton'
|
|
24
24
|
# singleton and merely a static, virtual node
|
25
25
|
class Concept::SKOS::Scheme
|
26
26
|
include Singleton
|
27
|
-
|
27
|
+
|
28
28
|
def self.rdf_class
|
29
29
|
:ConceptScheme
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def self.rdf_namespace
|
33
33
|
:skos
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def origin
|
37
37
|
:scheme
|
38
38
|
end
|
@@ -42,5 +42,5 @@ class Concept::SKOS::Scheme
|
|
42
42
|
raise "Namespace '#{rdf_namespace}' is not defined in IqRdf document." unless ns
|
43
43
|
IqRdf.build_uri(origin, ns.build_uri(self.class.rdf_class), &block)
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
end
|
data/app/models/label/base.rb
CHANGED
@@ -32,7 +32,7 @@ class Label::Base < ActiveRecord::Base
|
|
32
32
|
|
33
33
|
# ********* Scopes
|
34
34
|
|
35
|
-
|
35
|
+
def self.by_language(lang_code)
|
36
36
|
if (lang_code.is_a?(Array) && lang_code.include?(nil))
|
37
37
|
where(arel_table[:language].eq(nil).or(arel_table[:language].in(lang_code.compact)))
|
38
38
|
elsif lang_code.blank?
|
@@ -40,38 +40,40 @@ class Label::Base < ActiveRecord::Base
|
|
40
40
|
else
|
41
41
|
where(:language => lang_code)
|
42
42
|
end
|
43
|
-
|
43
|
+
end
|
44
44
|
|
45
|
-
|
45
|
+
def self.begins_with(letter)
|
46
46
|
where("LOWER(SUBSTR(#{Label::Base.table_name}.value, 1, 1)) = :letter", :letter => letter.to_s.downcase)
|
47
|
-
|
47
|
+
end
|
48
48
|
|
49
|
-
|
49
|
+
def self.missing_translation(lang, main_lang)
|
50
50
|
joins(:concepts).
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
51
|
+
joins(sanitize_sql(["LEFT OUTER JOIN labelings pref_labelings ON
|
52
|
+
pref_labelings.id <> labelings.id AND
|
53
|
+
pref_labelings.owner_id = concepts.id AND
|
54
|
+
pref_labelings.type = '%s'", Iqvoc::Concept.pref_labeling_class_name])).
|
55
|
+
joins(sanitize_sql(["LEFT OUTER JOIN labels pref_labels ON
|
56
|
+
pref_labels.id = pref_labelings.target_id AND
|
57
|
+
pref_labels.language = '%s'", lang])).
|
58
|
+
where('labelings.type = :class_name', :class_name => Iqvoc::Concept.pref_labeling_class_name).
|
59
|
+
where('pref_labels.id IS NULL').
|
60
|
+
where('labels.language = :lang', :lang => main_lang).
|
61
|
+
includes(:pref_labeled_concepts)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.by_query_value(query)
|
65
65
|
where(["LOWER(#{table_name}.value) LIKE ?", query.to_s.downcase])
|
66
|
-
|
66
|
+
end
|
67
67
|
|
68
68
|
# Attention: This means that even label classes without version controll will also
|
69
|
-
# have to set the published_at flag to be recognized as published
|
70
|
-
|
71
|
-
where(arel_table[
|
72
|
-
|
69
|
+
# have to set the published_at flag to be recognized as published!
|
70
|
+
def self.published
|
71
|
+
where(arel_table[:published_at].not_eq(nil))
|
72
|
+
end
|
73
73
|
|
74
|
-
|
74
|
+
def self.unpublished
|
75
|
+
where(arel_table[:published_at].eq(nil))
|
76
|
+
end
|
75
77
|
|
76
78
|
# ********* Methods
|
77
79
|
|
data/app/models/labeling/base.rb
CHANGED
@@ -29,29 +29,29 @@ class Labeling::Base < ActiveRecord::Base
|
|
29
29
|
|
30
30
|
# ********** Scopes
|
31
31
|
|
32
|
-
|
32
|
+
def self.by_concept(concept)
|
33
33
|
where(:owner_id => concept.id)
|
34
|
-
|
34
|
+
end
|
35
35
|
|
36
|
-
|
36
|
+
def self.by_label(label)
|
37
37
|
where(:target_id => label.id)
|
38
|
-
|
38
|
+
end
|
39
39
|
|
40
|
-
|
40
|
+
def self.concept_published
|
41
41
|
includes(:owner).merge(Concept::Base.published)
|
42
|
-
|
42
|
+
end
|
43
43
|
|
44
|
-
|
44
|
+
def self.label_published
|
45
45
|
includes(:target).merge(Label::Base.published)
|
46
|
-
|
46
|
+
end
|
47
47
|
|
48
|
-
|
48
|
+
def self.label_begins_with(letter)
|
49
49
|
includes(:target).merge(Label::Base.begins_with(letter))
|
50
|
-
|
50
|
+
end
|
51
51
|
|
52
|
-
|
52
|
+
def self.by_label_language(lang)
|
53
53
|
includes(:target).merge(Label::Base.by_language(lang.to_s))
|
54
|
-
|
54
|
+
end
|
55
55
|
|
56
56
|
# ********** Methods
|
57
57
|
|
@@ -24,9 +24,9 @@ class Labeling::SKOS::Base < Labeling::Base
|
|
24
24
|
|
25
25
|
# ********** Scopes
|
26
26
|
|
27
|
-
|
27
|
+
def self.by_label_with_language(label, language)
|
28
28
|
includes(:target).merge(self.label_class.where(:value => label, :language => language))
|
29
|
-
|
29
|
+
end
|
30
30
|
|
31
31
|
# ********** Methods
|
32
32
|
|
data/app/models/note/base.rb
CHANGED
@@ -36,27 +36,31 @@ class Note::Base < ActiveRecord::Base
|
|
36
36
|
|
37
37
|
# ********** Scopes
|
38
38
|
|
39
|
-
|
39
|
+
def self.by_language(lang_code)
|
40
40
|
if (lang_code.is_a?(Array) && lang_code.include?(nil))
|
41
41
|
where(arel_table[:language].eq(nil).or(arel_table[:language].in(lang_code.compact)))
|
42
42
|
else
|
43
43
|
where(:language => lang_code)
|
44
44
|
end
|
45
|
-
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
def self.by_query_value(query)
|
48
|
+
where(["LOWER(#{table_name}.value) LIKE ?", query.to_s.downcase])
|
49
|
+
end
|
50
50
|
|
51
|
-
|
51
|
+
def self.by_owner_type(klass)
|
52
52
|
where(:owner_type => klass.is_a?(ActiveRecord::Base) ? klass.name : klass)
|
53
|
-
|
53
|
+
end
|
54
54
|
|
55
|
-
|
55
|
+
def self.for_concepts
|
56
|
+
where(:owner_type => 'Concept::Base')
|
57
|
+
end
|
56
58
|
|
57
|
-
|
59
|
+
def self.for_labels
|
60
|
+
where(:owner_type => 'Label::Base')
|
61
|
+
end
|
58
62
|
|
59
|
-
|
63
|
+
def self.by_owner(owner)
|
60
64
|
if owner.is_a?(Label::Base)
|
61
65
|
for_labels.where(:owner_id => owner.id)
|
62
66
|
elsif owner.is_a?(Concept::Base)
|
@@ -64,7 +68,7 @@ class Note::Base < ActiveRecord::Base
|
|
64
68
|
else
|
65
69
|
raise "Note::Base.by_owner: Unknown owner (#{owner.inspect})"
|
66
70
|
end
|
67
|
-
|
71
|
+
end
|
68
72
|
|
69
73
|
# ********** Methods
|
70
74
|
|
@@ -5,7 +5,8 @@
|
|
5
5
|
concept.concept_relations_by_id(klass.name.to_relation_name),
|
6
6
|
:id => klass.name.to_relation_name,
|
7
7
|
:class => "entity_select",
|
8
|
-
:"data-query-url" => concepts_path(:format => :json,
|
8
|
+
:"data-query-url" => concepts_path(:format => :json,
|
9
|
+
:exclude_top_terms => klass != Iqvoc::Concept.broader_relation_class || nil),
|
9
10
|
:"data-entity-uri" => concept_path("{id}"),
|
10
11
|
:"data-singular" => klass.singular? || nil,
|
11
12
|
:"data-entities" => Iqvoc::Concept.base_class.editor_selectable.
|
data/config/database.yml
CHANGED
@@ -3,7 +3,6 @@ development:
|
|
3
3
|
encoding: utf8
|
4
4
|
reconnect: false
|
5
5
|
database: iqvoc_development
|
6
|
-
pool: 5
|
7
6
|
username: root
|
8
7
|
password:
|
9
8
|
hostname: 127.0.0.1
|
@@ -13,7 +12,6 @@ test:
|
|
13
12
|
encoding: utf8
|
14
13
|
reconnect: false
|
15
14
|
database: iqvoc_test
|
16
|
-
pool: 5
|
17
15
|
username: root
|
18
16
|
password:
|
19
17
|
hostname: 127.0.0.1
|
@@ -22,8 +20,7 @@ production:
|
|
22
20
|
adapter: mysql2
|
23
21
|
encoding: utf8
|
24
22
|
reconnect: false
|
25
|
-
database:
|
26
|
-
pool: 5
|
23
|
+
database: iqvoc_production
|
27
24
|
username: root
|
28
25
|
password:
|
29
26
|
hostname: 127.0.0.1
|
@@ -25,6 +25,6 @@ if Iqvoc.const_defined?(:Application)
|
|
25
25
|
|
26
26
|
# Run `rake secret` and uncomment the following line
|
27
27
|
# Replace the secret-placeholder with your generated token
|
28
|
-
Iqvoc::Application.config.secret_token = '
|
28
|
+
Iqvoc::Application.config.secret_token = 'ef1f801c911b45ded2944aad3121244bfabf231631d102e6e120da8639c47eb6aa4ae7df733f0d539951cbc4e399e6050f46bc279d6a85d57135688394b87c5a'
|
29
29
|
|
30
30
|
end
|
data/config/routes.rb
CHANGED
@@ -34,7 +34,10 @@ module Iqvoc
|
|
34
34
|
|
35
35
|
def handle_access_denied(exception)
|
36
36
|
@exception = exception
|
37
|
-
|
37
|
+
respond_to do |format|
|
38
|
+
format.html { render :template => 'errors/access_denied', :status => 403 }
|
39
|
+
format.any { head 404 }
|
40
|
+
end
|
38
41
|
end
|
39
42
|
|
40
43
|
def handle_multiple_choices(exception)
|
@@ -47,8 +50,8 @@ module Iqvoc
|
|
47
50
|
SearchResultsController.prepare_basic_variables(self)
|
48
51
|
|
49
52
|
respond_to do |format|
|
50
|
-
format.html { render :template => 'errors/not_found', :status =>
|
51
|
-
format.any
|
53
|
+
format.html { render :template => 'errors/not_found', :status => 404 }
|
54
|
+
format.any { head 404 }
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
@@ -1,5 +1,39 @@
|
|
1
1
|
require 'iqvoc'
|
2
2
|
|
3
|
+
# inject template name
|
4
|
+
class ActionView::TemplateRenderer
|
5
|
+
|
6
|
+
def render_with_source_comment(context, options)
|
7
|
+
res = render_without_source_comment(context, options)
|
8
|
+
template = determine_template(options)
|
9
|
+
if template.formats.include?(:html)
|
10
|
+
"<!-- Template: #{template.inspect} -->\n".html_safe << res <<
|
11
|
+
"<!-- /Template -->\n".html_safe
|
12
|
+
else
|
13
|
+
res
|
14
|
+
end
|
15
|
+
end
|
16
|
+
alias_method_chain :render, :source_comment
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
# inject partial name
|
21
|
+
class ActionView::PartialRenderer
|
22
|
+
|
23
|
+
def render_with_source_comment(context, options, block)
|
24
|
+
res = render_without_source_comment(context, options, block)
|
25
|
+
template = find_template
|
26
|
+
if template.formats.include?(:html)
|
27
|
+
"<!-- Partial: #{template.inspect} -->\n".html_safe << res <<
|
28
|
+
"<!-- /Partial -->\n".html_safe
|
29
|
+
else
|
30
|
+
res
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method_chain :render, :source_comment
|
34
|
+
|
35
|
+
end
|
36
|
+
|
3
37
|
module Iqvoc::Environments
|
4
38
|
|
5
39
|
def self.setup_development(config)
|
@@ -63,4 +97,5 @@ module Iqvoc::Environments
|
|
63
97
|
# mode.
|
64
98
|
config.virtuoso_sync_threaded = false
|
65
99
|
end
|
100
|
+
|
66
101
|
end
|
@@ -59,6 +59,26 @@ module Iqvoc::Environments
|
|
59
59
|
|
60
60
|
# Send deprecation notices to registered listeners
|
61
61
|
config.active_support.deprecation = :notify
|
62
|
+
|
63
|
+
# The JDBC driver URL for the connection to the virtuoso triple store.
|
64
|
+
# Login credentials have to be stored here too. See
|
65
|
+
# http://docs.openlinksw.com/virtuoso/VirtuosoDriverJDBC.html#jdbcurl4mat for
|
66
|
+
# more details.
|
67
|
+
# Example: "jdbc:virtuoso://localhost:1111/UID=dba/PWD=dba"
|
68
|
+
# Use nil to disable virtuoso triple synchronization
|
69
|
+
# Rails.application.config.virtuoso_jdbc_driver_url = "jdbc:virtuoso://virtuoso.dyndns.org:1111/UID=iqvoc/PWD=vocpass!/charset=UTF-8"
|
70
|
+
config.virtuoso_jdbc_driver_url = nil
|
71
|
+
|
72
|
+
# Set up the virtuoso synchronization (which is a triggered pull from the
|
73
|
+
# virtuoso server) to be run in a new thread.
|
74
|
+
# This is needed in environments where the web server only runs in a single
|
75
|
+
# process/thread (mostly in development environments).
|
76
|
+
# When a synchronization would be triggered e.g. from a running
|
77
|
+
# update action in the UPB, the update would trigger virtuoso to do a HTTP GET
|
78
|
+
# back to the UPB to fetch the RDF data. But the only process in the UPB would be
|
79
|
+
# blocked by the update... => Deadlock. You can avoid this by using the threaded
|
80
|
+
# mode.
|
81
|
+
config.virtuoso_sync_threaded = false
|
62
82
|
end
|
63
83
|
|
64
84
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'iqvoc'
|
2
|
-
|
3
1
|
module Iqvoc
|
4
2
|
module Maker
|
5
3
|
|
@@ -118,7 +116,7 @@ module Iqvoc
|
|
118
116
|
|
119
117
|
defaults = { # NB: must use strings, not symbols as keys due to YAML
|
120
118
|
:value => value, # intentionally not a string; symbol takes precedence
|
121
|
-
"origin" =>
|
119
|
+
"origin" => Iqvoc::Origin.new(value).to_s,
|
122
120
|
"language" => Iqvoc::Concept.pref_labeling_languages.first,
|
123
121
|
"published_at" => 2.days.ago
|
124
122
|
}
|
data/lib/iqvoc/origin.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 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
|
+
# Provides utilities to replace special chars etc in
|
18
|
+
# texts to generate a valid turtle compatible id (an url slug):
|
19
|
+
# Iqvoc::Origin.new("fübar").to_s # => "fuebar"
|
20
|
+
#
|
21
|
+
# Note that .to_s respects eventually previously executed method chains
|
22
|
+
# Just calling "to_s" runs all registered filters.
|
23
|
+
# Prepending "to_s" with a specific filter method only runs the given filter:
|
24
|
+
# Iqvoc::Origin.new("fübar").replace_umlauts.to_s # => "fuebar"
|
25
|
+
#
|
26
|
+
# Adding your own filter classes is easy:
|
27
|
+
# class FoobarStripper < Iqvoc::Origin::Filters::GenericFilter
|
28
|
+
# def call(obj, str)
|
29
|
+
# str = str.gsub("foobar", "")
|
30
|
+
# run(obj, str)
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# Iqvoc::Origin::Filters.register(:strip_foobars, FoobarStripper)
|
34
|
+
#
|
35
|
+
module Iqvoc
|
36
|
+
class Origin
|
37
|
+
module Filters
|
38
|
+
class GenericFilter
|
39
|
+
def call(obj, str)
|
40
|
+
# do what has to be done with str
|
41
|
+
# afterwards: make sure to pass "obj" and your modified "str" to "run()"
|
42
|
+
run(obj, str)
|
43
|
+
end
|
44
|
+
|
45
|
+
def run(obj, str)
|
46
|
+
obj.tap do |obj|
|
47
|
+
obj.value = str
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class UmlautReplacer < GenericFilter
|
53
|
+
def call(obj, str)
|
54
|
+
str = str.gsub(/Ö/, 'Oe').
|
55
|
+
gsub(/Ä/, 'Ae').
|
56
|
+
gsub(/Ü/, 'Ue').
|
57
|
+
gsub(/ö/, 'oe').
|
58
|
+
gsub(/ä/, 'ae').
|
59
|
+
gsub(/ü/, 'ue').
|
60
|
+
gsub(/ß/, 'ss')
|
61
|
+
|
62
|
+
run(obj, str)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class WhitespaceReplacer < GenericFilter
|
67
|
+
def call(obj, str)
|
68
|
+
str = str.gsub(/\s([a-zA-Z])?/) do
|
69
|
+
$1.to_s.upcase
|
70
|
+
end
|
71
|
+
|
72
|
+
run(obj, str)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class SpecialCharReplacer < GenericFilter
|
77
|
+
def call(obj, str)
|
78
|
+
str = str.gsub(/[(\[:]/, "--").
|
79
|
+
gsub(/[)\]'""]/, "").
|
80
|
+
gsub(/[,\.\/&;]/, '-')
|
81
|
+
|
82
|
+
run(obj, str)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class LeadingNumberHandler < GenericFilter
|
87
|
+
def call(obj, str)
|
88
|
+
str = str.gsub(/^[0-9].*$/) do |match|
|
89
|
+
"_#{match}"
|
90
|
+
end
|
91
|
+
|
92
|
+
run(obj, str)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
@filters = {
|
97
|
+
:replace_umlauts => UmlautReplacer,
|
98
|
+
:replace_whitespace => WhitespaceReplacer,
|
99
|
+
:replace_special_chars => SpecialCharReplacer,
|
100
|
+
:handle_leading_numbers => LeadingNumberHandler
|
101
|
+
}
|
102
|
+
|
103
|
+
def self.register(name, klass)
|
104
|
+
@filters[name.to_sym] = klass
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.registered
|
108
|
+
@filters
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
attr_accessor :initial_value, :value, :filters
|
113
|
+
|
114
|
+
def initialize(value)
|
115
|
+
self.initial_value = value.to_s
|
116
|
+
self.value = initial_value
|
117
|
+
end
|
118
|
+
|
119
|
+
def touched?
|
120
|
+
value != initial_value
|
121
|
+
end
|
122
|
+
|
123
|
+
def run_filters!
|
124
|
+
Filters.registered.each do |key, filter_class|
|
125
|
+
filter_class.new.call(self, value)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def method_missing(meth, *args)
|
130
|
+
if Filters.registered.keys.include?(meth.to_sym)
|
131
|
+
Filters.registered[meth.to_sym].new.call(self, value)
|
132
|
+
else
|
133
|
+
super
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_s
|
138
|
+
return value if touched?
|
139
|
+
run_filters!
|
140
|
+
value
|
141
|
+
end
|
142
|
+
|
143
|
+
def inspect
|
144
|
+
"#<Iqvoc::Origin:0x%08x>" % object_id
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|