glossarist 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 34ea633c0a5f8f609e12c72d8a835fd8675f8cf52996633ed9c84c9d304f73cc
4
+ data.tar.gz: a855be248a3ae9d9435969643660210a30ae1f7912b0c714ed4a7d1ee09632f3
5
+ SHA512:
6
+ metadata.gz: b98c00342f4107b361ddc27f7e6323540c1335a339b54594c7944a4d45e1dcf4746070f38cd91934320a39d2616305055f9cf62b88253deb1842686f238cbed1
7
+ data.tar.gz: 8ec6121d3a5dd24e3c032bf92ab4e31ceefaf451aa81bf8f395c4d78e34e2ec1c594173f997c646af9f2a5b094db490a9f3fdcec1f8d4a57b8c79afa5107aa7b
data/.editorconfig ADDED
@@ -0,0 +1,15 @@
1
+ # EditorConfig is awesome: http://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ # Unix-style newlines with a newline ending every file
7
+ [*]
8
+ charset = utf-8
9
+ end_of_line = lf
10
+
11
+ [{*.adoc,*.html,*.js,*.json,*.rake,*.rb,*.rf,*.yaml,*.yml,Rakefile,rakefile}]
12
+ indent_style = space
13
+ indent_size = 2
14
+ insert_final_newline = true
15
+ trim_trailing_whitespace = true
@@ -0,0 +1,37 @@
1
+ name: Test
2
+
3
+ on:
4
+ - push
5
+ - pull_request
6
+ - workflow_dispatch
7
+
8
+ jobs:
9
+ build:
10
+ name: Ruby ${{ matrix.ruby }}
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ ruby:
17
+ - "3.0"
18
+ - "2.7"
19
+ - "2.6"
20
+ - "2.5"
21
+ - "2.4"
22
+
23
+ name: Run tests
24
+ runs-on: ubuntu-latest
25
+
26
+ steps:
27
+ - name: Fetch source code
28
+ uses: actions/checkout@v2
29
+
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: ${{ matrix.ruby }}
34
+ bundler-cache: true
35
+
36
+ - name: Run tests
37
+ run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ /Gemfile.lock
11
+
12
+ # RSpec failure tracking
13
+ .rspec_status
14
+
15
+ # RuboCop caches
16
+ .rubocop-http---*
17
+ .rubocop-https---*
18
+
data/.hound.yml ADDED
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ enabled: true
3
+ config_file: .rubocop.yml
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,35 @@
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
3
+
4
+ # local repo-specific modifications
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 2.4
8
+
9
+ # This one breaks plenty of RSpec idioms.
10
+ Lint/AmbiguousBlockAssociation:
11
+ Exclude:
12
+ - "spec/**/*"
13
+
14
+ # Defining a constant or class inside RSpec.describe block
15
+ # sometimes makes sense.
16
+ Lint/ConstantDefinitionInBlock:
17
+ Exclude:
18
+ - "spec/**/*"
19
+
20
+ # This requirement is silly to me.
21
+ Style/AccessModifierDeclarations:
22
+ Enabled: false
23
+
24
+ # Makes little sense for Glossarist models, as these attr_accessors should all
25
+ # be documented eventually.
26
+ Style/AccessorGrouping:
27
+ Enabled: false
28
+
29
+ # This requirement is silly to me.
30
+ Style/ClassCheck:
31
+ Enabled: false
32
+
33
+ # This requirement is silly to me.
34
+ Style/SingleArgumentDig:
35
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2021, Ribose
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.adoc ADDED
@@ -0,0 +1,11 @@
1
+ = Glossarist
2
+
3
+ == Credits
4
+
5
+ This gem is developed, maintained and funded by
6
+ https://www.ribose.com[Ribose Inc.]
7
+
8
+ == License
9
+
10
+ The gem is available as open source under the terms of the
11
+ https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/glossarist/version"
4
+
5
+ all_files_in_git = Dir.chdir(File.expand_path(__dir__)) do
6
+ `git ls-files -z`.split("\x0")
7
+ end
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.name = "glossarist"
11
+ spec.version = Glossarist::VERSION
12
+ spec.authors = ["Ribose"]
13
+ spec.email = ["open.source@ribose.com"]
14
+
15
+ spec.summary =
16
+ "Concept models for terminology glossaries conforming ISO 10241-1."
17
+ spec.homepage = "https://github.com/glossarist/glossarist-ruby"
18
+ spec.license = "BSD-2-Clause"
19
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
20
+
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = spec.homepage
23
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ spec.files = all_files_in_git
27
+ .reject { |f| f.match(%r{\A(?:test|spec|features|bin|\.)/}) }
28
+
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_development_dependency "pry", "~> 0.14.0"
34
+ spec.add_development_dependency "rake", "~> 13.0"
35
+ spec.add_development_dependency "rspec", "~> 3.10"
36
+ end
data/lib/glossarist.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2021 Ribose Inc.
4
+ #
5
+
6
+ require "psych"
7
+
8
+ require_relative "glossarist/version"
9
+
10
+ require_relative "glossarist/model"
11
+ require_relative "glossarist/concept"
12
+ require_relative "glossarist/collection"
13
+ require_relative "glossarist/localized_concept"
14
+
15
+ module Glossarist
16
+ class Error < StandardError; end
17
+ # Your code goes here...
18
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2021 Ribose Inc.
4
+ #
5
+
6
+ module Glossarist
7
+ # @todo Add support for lazy concept loading.
8
+ # @todo Consider extracting persistence backend to a separate class.
9
+ class Collection
10
+ include Enumerable
11
+
12
+ # Path to concepts directory.
13
+ # @return [String]
14
+ attr_accessor :path
15
+
16
+ # @param path [String]
17
+ # concepts directory path, either absolute or relative to CWD
18
+ def initialize(path: nil)
19
+ @path = path
20
+ @index = {}
21
+ end
22
+
23
+ def each(&block)
24
+ @index.each_value(&block)
25
+ end
26
+
27
+ # Returns concept with given ID, if it is present in collection, or +nil+
28
+ # otherwise.
29
+ #
30
+ # @param id [String]
31
+ # Concept ID
32
+ # @return [Concept, nil]
33
+ def fetch(id)
34
+ @index[id]
35
+ end
36
+
37
+ alias :[] :fetch
38
+
39
+ # If concept with given ID is present in this collection, returns that
40
+ # concept. Otherwise, instantiates a new concept, adds it to
41
+ # the collection, and returns it.
42
+ #
43
+ # @param id [String]
44
+ # Concept ID
45
+ # @return [Concept]
46
+ def fetch_or_initialize(id)
47
+ fetch(id) or store(Concept.new(id: id))
48
+ end
49
+
50
+ # Adds concept to the collection. If collection contains a concept with
51
+ # the same ID already, that concept is replaced.
52
+ #
53
+ # @param concept [Concept]
54
+ # concept about to be added
55
+ def store(concept)
56
+ @index[concept.id] = concept
57
+ end
58
+
59
+ alias :<< :store
60
+
61
+ # Reads all concepts from files.
62
+ def load_concepts
63
+ Dir.glob(concepts_glob) do |filename|
64
+ store(load_concept_from_file(filename))
65
+ end
66
+ end
67
+
68
+ private def load_concept_from_file(filename)
69
+ Concept.from_h(Psych.safe_load(File.read(filename)))
70
+ end
71
+
72
+ # Writes all concepts to files.
73
+ def save_concepts
74
+ @index.each_value &method(:save_concept_to_file)
75
+ end
76
+
77
+ private def save_concept_to_file(concept)
78
+ filename = File.join(path, "concept-#{concept.id}.yaml")
79
+ File.write(filename, Psych.dump(concept.to_h))
80
+ end
81
+
82
+ private def concepts_glob
83
+ File.join(path, "concept-*.{yaml,yml}")
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2021 Ribose Inc.
4
+ #
5
+
6
+ module Glossarist
7
+ class Concept < Model
8
+ # Concept ID.
9
+ # @return [String]
10
+ attr_accessor :id
11
+
12
+ # All localizations for this concept.
13
+ #
14
+ # Keys are language codes and values are instances of {LocalizedConcept}.
15
+ # @return [Hash<String, LocalizedConcept>]
16
+ attr_reader :localizations
17
+
18
+ def initialize(*)
19
+ @localizations = {}
20
+ super
21
+ end
22
+
23
+ # Adds concept localization.
24
+ # @param localized_concept [LocalizedConcept]
25
+ def add_localization(localized_concept)
26
+ lang = localized_concept.language_code
27
+ localizations.store(lang, localized_concept)
28
+ end
29
+
30
+ alias :add_l10n :add_localization
31
+
32
+ # Returns concept localization.
33
+ # @param lang [String] language code
34
+ # @return [LocalizedConcept]
35
+ def localization(lang)
36
+ localizations[lang]
37
+ end
38
+
39
+ alias :l10n :localization
40
+
41
+ def to_h
42
+ {
43
+ "termid" => id,
44
+ "term" => default_designation,
45
+ "related" => related_concepts,
46
+ **localizations.transform_values(&:to_h),
47
+ }.compact
48
+ end
49
+
50
+ # @deprecated For legacy reasons only.
51
+ # Implicit conversion (i.e. {#to_hash} alias) will be removed soon.
52
+ alias :to_hash :to_h
53
+
54
+ # rubocop:disable Metrics/AbcSize, Style/RescueModifier
55
+ def self.from_h(hash)
56
+ new.tap do |concept|
57
+ concept.id = hash.dig("termid")
58
+
59
+ hash.values
60
+ .grep(Hash)
61
+ .map { |subhash| LocalizedConcept.from_h(subhash) rescue nil }
62
+ .compact
63
+ .each { |lc| concept.add_l10n lc }
64
+
65
+ concept.l10n("eng")&.superseded_concepts = hash.dig("related_concepts")
66
+ end
67
+ end
68
+ # rubocop:enable Metrics/AbcSize, Style/RescueModifier
69
+
70
+ def default_designation
71
+ localized = localization("eng") || localizations.values.first
72
+ localized&.terms&.dig(0, "designation")
73
+ end
74
+
75
+ def related_concepts
76
+ # TODO Someday other relation types too
77
+ arr = [localization("eng")&.superseded_concepts].flatten.compact
78
+ arr.empty? ? nil : arr
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2021 Ribose Inc.
4
+ #
5
+
6
+ module Glossarist
7
+ class LocalizedConcept < Model
8
+ # Needs to be identical with {Concept#id}.
9
+ # @todo Here for legacy reasons. Will be removed eventually.
10
+ attr_accessor :id
11
+
12
+ # ISO 639-2 code for terminology.
13
+ # @see https://www.loc.gov/standards/iso639-2/php/code_list.php code list
14
+ # @return [String]
15
+ attr_accessor :language_code
16
+
17
+ # Concept designations.
18
+ # @todo Alias +terms+ exists only for legacy reasons and will be removed.
19
+ # @todo Right now accepts hashes for legacy reasons, but they will be
20
+ # replaced with dedicated classes.
21
+ # @return [Array<Hash>]
22
+ attr_accessor :designations
23
+ alias :terms :designations
24
+ alias :terms= :designations=
25
+
26
+ # @return [Array<String>]
27
+ attr_accessor :notes
28
+
29
+ # @return [Array<String>]
30
+ attr_accessor :examples
31
+
32
+ # Concept definition.
33
+ # @todo Support multiple definitions.
34
+ # @return [String]
35
+ attr_accessor :definition
36
+
37
+ # @todo Right now accepts hashes for legacy reasons, but they will be
38
+ # replaced with dedicated classes.
39
+ # @return [Hash]
40
+ attr_accessor :authoritative_source
41
+
42
+ # Must be one of the following:
43
+ # +notValid+, +valid+, +superseded+, +retired+.
44
+ # @todo Proper type checking.
45
+ # @note Works with strings, but soon they may be replaced with symbols.
46
+ # @return [String]
47
+ attr_accessor :entry_status
48
+
49
+ # Must be one of the following:
50
+ # +preferred+, +admitted+, +deprecated+.
51
+ # @todo Proper type checking.
52
+ # @note Works with strings, but soon they may be replaced with symbols.
53
+ # @return [String]
54
+ attr_accessor :classification
55
+
56
+ attr_accessor :review_date
57
+ attr_accessor :review_decision_date
58
+ attr_accessor :review_decision_event
59
+
60
+ attr_accessor :date_accepted
61
+ attr_accessor :date_amended
62
+
63
+ # @todo Here for legacy reasons. Will be moved to Concept.
64
+ # @todo Right now is an array of hashes for legacy reasons, but these hashes
65
+ # will be replaced with some dedicated class.
66
+ # @todo Should be read-only, but for now it is not for legacy reasons.
67
+ # Don't use the setter.
68
+ # @return [Array<Hash>]
69
+ attr_accessor :superseded_concepts
70
+
71
+ def initialize(*)
72
+ @examples = []
73
+ @notes = []
74
+ @designations = []
75
+ super
76
+ end
77
+
78
+ def to_h # rubocop:disable Metrics/MethodLength
79
+ {
80
+ "id" => id,
81
+ "terms" => terms,
82
+ "definition" => definition,
83
+ "language_code" => language_code,
84
+ "notes" => notes,
85
+ "examples" => examples,
86
+ "entry_status" => entry_status,
87
+ "classification" => classification,
88
+ "authoritative_source" => authoritative_source,
89
+ "date_accepted" => date_accepted,
90
+ "date_amended" => date_amended,
91
+ "review_date" => review_date,
92
+ "review_decision_date" => review_decision_date,
93
+ "review_decision_event" => review_decision_event,
94
+ }.compact
95
+ end
96
+
97
+ # @deprecated For legacy reasons only.
98
+ # Implicit conversion (i.e. {#to_hash} alias) will be removed soon.
99
+ alias :to_hash :to_h
100
+ end
101
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2021 Ribose Inc.
4
+ #
5
+
6
+ module Glossarist
7
+ class Model
8
+ def initialize(attributes = {})
9
+ attributes.each_pair { |k, v| set_attribute(k, v) }
10
+ end
11
+
12
+ def set_attribute(name, value)
13
+ public_send("#{name}=", value)
14
+ rescue NoMethodError
15
+ raise ArgumentError, "#{self.class.name} does not have " +
16
+ "attribute #{name} defined or the attribute is read only."
17
+ end
18
+
19
+ def self.from_h(hash)
20
+ new(hash)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2021 Ribose Inc.
4
+ #
5
+
6
+ module Glossarist
7
+ VERSION = "0.1.0"
8
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glossarist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ribose
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.14.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.10'
55
+ description:
56
+ email:
57
+ - open.source@ribose.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".editorconfig"
63
+ - ".github/workflows/test.yml"
64
+ - ".gitignore"
65
+ - ".hound.yml"
66
+ - ".rspec"
67
+ - ".rubocop.yml"
68
+ - Gemfile
69
+ - LICENSE.txt
70
+ - README.adoc
71
+ - Rakefile
72
+ - glossarist.gemspec
73
+ - lib/glossarist.rb
74
+ - lib/glossarist/collection.rb
75
+ - lib/glossarist/concept.rb
76
+ - lib/glossarist/localized_concept.rb
77
+ - lib/glossarist/model.rb
78
+ - lib/glossarist/version.rb
79
+ homepage: https://github.com/glossarist/glossarist-ruby
80
+ licenses:
81
+ - BSD-2-Clause
82
+ metadata:
83
+ homepage_uri: https://github.com/glossarist/glossarist-ruby
84
+ source_code_uri: https://github.com/glossarist/glossarist-ruby
85
+ bug_tracker_uri: https://github.com/glossarist/glossarist-ruby/issues
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 2.4.0
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.1.4
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Concept models for terminology glossaries conforming ISO 10241-1.
105
+ test_files: []