locabulary 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +46 -0
- data/.rspec +1 -0
- data/.rubocop_todo.yml +21 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/README.md +8 -1
- data/Rakefile +37 -4
- data/data/administrative_units.json +374 -806
- data/lib/locabulary/exceptions.rb +25 -0
- data/lib/locabulary/items/administrative_unit.rb +65 -0
- data/lib/locabulary/items/base.rb +105 -0
- data/lib/locabulary/items.rb +32 -0
- data/lib/locabulary/json_creator.rb +105 -0
- data/lib/locabulary/schema.rb +11 -20
- data/lib/locabulary/version.rb +3 -0
- data/lib/locabulary.rb +67 -88
- data/locabulary.gemspec +8 -2
- data/script/update_data_files.sh +7 -2
- metadata +97 -4
- data/script/json_creator.rb +0 -129
@@ -0,0 +1,25 @@
|
|
1
|
+
module Locabulary
|
2
|
+
# Container for all exceptions in the Locabulary ecosystem
|
3
|
+
module Exceptions
|
4
|
+
class RuntimeError < ::RuntimeError
|
5
|
+
end
|
6
|
+
|
7
|
+
# There is a problem with the hierarchy; A child is being defined without a defined parent.
|
8
|
+
class MissingHierarchicalParentError < RuntimeError
|
9
|
+
attr_reader :predicate_name, :error
|
10
|
+
def initialize(predicate_name, error)
|
11
|
+
@predicate_name = predicate_name
|
12
|
+
@error = error
|
13
|
+
super("Expected #{predicate_name.inspect} to have a welformed tree. Error: #{error}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# There is a problem with the hierarchy; Instead of a tree we have a multitude of trees
|
18
|
+
class TooManyHierarchicalRootsError < RuntimeError
|
19
|
+
attr_reader :predicate_name, :roots
|
20
|
+
def initialize(predicate_name, roots)
|
21
|
+
super("Expected fewer root slugs for #{predicate_name.inspect}. Roots encountered: #{roots.inspect}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'locabulary/exceptions'
|
2
|
+
require 'locabulary/items/base'
|
3
|
+
|
4
|
+
module Locabulary
|
5
|
+
module Items
|
6
|
+
# Responsible for exposing the data structure logic of the Administrative Units
|
7
|
+
#
|
8
|
+
# @see ./data/administrative_units.json
|
9
|
+
class AdministrativeUnit < Locabulary::Items::Base
|
10
|
+
configure do |config|
|
11
|
+
config.attribute_names = [
|
12
|
+
:predicate_name, :term_label, :term_uri, :description, :grouping, :classification, :affiliation, :default_presentation_sequence,
|
13
|
+
:homepage, :activated_on, :deactivated_on
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
# [String] What is the URL of the homepage. Please note the term_uri is reserved for something that is more resolvable by machines.
|
18
|
+
# And while the homepage may look resolvable, it is not as meaningful for longterm preservation.
|
19
|
+
attr_reader :homepage
|
20
|
+
attr_reader :classification
|
21
|
+
attr_reader :grouping
|
22
|
+
attr_reader :affiliation
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_writer :homepage, :classification, :grouping, :affiliation
|
27
|
+
|
28
|
+
public
|
29
|
+
|
30
|
+
def initialize(*args)
|
31
|
+
super
|
32
|
+
@children = []
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :children
|
36
|
+
|
37
|
+
HIERARCHY_SEPARATOR = '::'.freeze
|
38
|
+
def slugs
|
39
|
+
term_label.split(HIERARCHY_SEPARATOR)
|
40
|
+
end
|
41
|
+
|
42
|
+
def parent_slugs
|
43
|
+
slugs[0..-2]
|
44
|
+
end
|
45
|
+
|
46
|
+
def parent_term_label
|
47
|
+
parent_slugs.join(HIERARCHY_SEPARATOR)
|
48
|
+
end
|
49
|
+
|
50
|
+
def root_slug
|
51
|
+
slugs[0]
|
52
|
+
end
|
53
|
+
|
54
|
+
def selectable?
|
55
|
+
children.count == 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def selectable_label
|
59
|
+
slugs[1..-1].join(HIERARCHY_SEPARATOR)
|
60
|
+
end
|
61
|
+
|
62
|
+
alias selectable_id id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'dry/configurable'
|
2
|
+
module Locabulary
|
3
|
+
module Items
|
4
|
+
# A singular item in the controlled vocubulary.
|
5
|
+
# @see https://en.wikipedia.org/wiki/Resource_Description_Framework
|
6
|
+
class Base
|
7
|
+
extend Dry::Configurable
|
8
|
+
|
9
|
+
setting :attribute_names, [
|
10
|
+
:predicate_name, :term_label, :term_uri, :deposit_label, :description, :grouping, :affiliation, :default_presentation_sequence,
|
11
|
+
:activated_on, :deactivated_on
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def attribute_names
|
15
|
+
self.class.config.attribute_names
|
16
|
+
end
|
17
|
+
|
18
|
+
# [String] the trait for a given subject that we are describing by way of the term_label/term_uri
|
19
|
+
attr_reader :predicate_name
|
20
|
+
|
21
|
+
# [String] the human friendly version of the meaning for this given trait
|
22
|
+
# @note For the time being, please regard the term_label as immutable; If you need a modification, deactivate this one and activate a
|
23
|
+
# new one
|
24
|
+
attr_reader :term_label
|
25
|
+
|
26
|
+
# [String] the machine friendly version of the meaning for this given trait
|
27
|
+
# @note For the time being, please regard the term_uri as immutable; If you need a modification, deactivate this one and activate a
|
28
|
+
# new one
|
29
|
+
attr_reader :term_uri
|
30
|
+
|
31
|
+
# [String] a side-car of more exhaustive information related to this particular term
|
32
|
+
attr_reader :description
|
33
|
+
|
34
|
+
# [Date] When was this particular item activated
|
35
|
+
attr_reader :activated_on
|
36
|
+
|
37
|
+
# [Date] When was this particular item deactivated
|
38
|
+
attr_reader :deactivated_on
|
39
|
+
|
40
|
+
# [Integer, nil] What is the order in which
|
41
|
+
# @see Locabulary::Item#presentation_sequence for details on how this is calculated
|
42
|
+
attr_reader :default_presentation_sequence
|
43
|
+
|
44
|
+
# @deprecated
|
45
|
+
attr_reader :deposit_label
|
46
|
+
|
47
|
+
# @deprecated
|
48
|
+
attr_reader :grouping
|
49
|
+
|
50
|
+
# @deprecated
|
51
|
+
attr_reader :affiliation
|
52
|
+
|
53
|
+
def initialize(attributes = {})
|
54
|
+
attribute_names.each do |key|
|
55
|
+
value = attributes.fetch(key) { attributes.fetch(key.to_s, nil) }
|
56
|
+
send("#{key}=", value)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_h
|
61
|
+
attribute_names.each_with_object({}) do |key, mem|
|
62
|
+
mem[key.to_s] = send(key) unless send(key).to_s.strip == ''
|
63
|
+
mem
|
64
|
+
end
|
65
|
+
end
|
66
|
+
alias as_json to_h
|
67
|
+
|
68
|
+
def to_persistence_format_for_fedora
|
69
|
+
return term_uri unless term_uri.to_s.strip == ''
|
70
|
+
term_label
|
71
|
+
end
|
72
|
+
alias id to_persistence_format_for_fedora
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
attr_writer(*config.attribute_names)
|
77
|
+
|
78
|
+
def predicate_name=(input)
|
79
|
+
@predicate_name = input.to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_presentation_sequence=(input)
|
83
|
+
@default_presentation_sequence = input.to_s.strip == '' ? nil : input.to_i
|
84
|
+
end
|
85
|
+
|
86
|
+
public
|
87
|
+
|
88
|
+
include Comparable
|
89
|
+
|
90
|
+
def <=>(other)
|
91
|
+
predicate_name_sort = predicate_name <=> other.predicate_name
|
92
|
+
return predicate_name_sort unless predicate_name_sort == 0
|
93
|
+
presentation_sequence_sort = presentation_sequence <=> other.presentation_sequence
|
94
|
+
return presentation_sequence_sort unless presentation_sequence_sort == 0
|
95
|
+
term_label <=> other.term_label
|
96
|
+
end
|
97
|
+
|
98
|
+
SORT_SEQUENCE_FOR_NIL = 100_000_000
|
99
|
+
private_constant :SORT_SEQUENCE_FOR_NIL
|
100
|
+
def presentation_sequence
|
101
|
+
default_presentation_sequence || SORT_SEQUENCE_FOR_NIL
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'locabulary/items/base'
|
2
|
+
require 'hanami/utils/string'
|
3
|
+
module Locabulary
|
4
|
+
# A container for the various types of Locabulary Items
|
5
|
+
module Items
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# @api public
|
9
|
+
# @since 0.2.1
|
10
|
+
def build(options = {})
|
11
|
+
predicate_name = options.fetch(:predicate_name) { options.fetch('predicate_name') }
|
12
|
+
builder_for(predicate_name: predicate_name).call(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api public
|
16
|
+
# @since 0.2.1
|
17
|
+
#
|
18
|
+
# @param options [Hash]
|
19
|
+
# @option predicate_name [String] Used for lookup of the correct Locabulary::Item type
|
20
|
+
def builder_for(options = {})
|
21
|
+
predicate_name = options.fetch(:predicate_name)
|
22
|
+
possible_class_name_for_predicate_name = Hanami::Utils::String.new(predicate_name).singularize.classify
|
23
|
+
klass = begin
|
24
|
+
Items.const_get(possible_class_name_for_predicate_name)
|
25
|
+
rescue NameError
|
26
|
+
Items::Base
|
27
|
+
end
|
28
|
+
klass.method(:new)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
require 'locabulary/items/administrative_unit'
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "google/api_client"
|
2
|
+
require "google_drive"
|
3
|
+
require 'highline/import'
|
4
|
+
require 'locabulary'
|
5
|
+
require 'locabulary/items'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Locabulary
|
9
|
+
# Responsible for capturing predicate_name from a given source and writing it to a file
|
10
|
+
class JsonCreator
|
11
|
+
def initialize(document_key, predicate_name, data_fetcher = default_data_fetcher)
|
12
|
+
@document_key = document_key
|
13
|
+
@predicate_name = predicate_name
|
14
|
+
@output_filepath = Locabulary.filename_for_predicate_name(predicate_name: predicate_name)
|
15
|
+
@data_fetcher = data_fetcher
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :document_key, :predicate_name, :data_fetcher, :spreadsheet_data, :json_data
|
19
|
+
attr_accessor :output_filepath
|
20
|
+
|
21
|
+
def create_or_update
|
22
|
+
rows = data_fetcher.call(document_key)
|
23
|
+
data = extract_data_from(rows)
|
24
|
+
convert_to_json(data)
|
25
|
+
end
|
26
|
+
|
27
|
+
# :nocov:
|
28
|
+
def write_to_file
|
29
|
+
File.open(output_filepath, "w") do |f|
|
30
|
+
f.puts json_data
|
31
|
+
end
|
32
|
+
end
|
33
|
+
# :nocov:
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def extract_data_from(rows)
|
38
|
+
spreadsheet_data = []
|
39
|
+
header = rows[0]
|
40
|
+
rows[1..-1].each do |row|
|
41
|
+
# The activated_on is a present hack reflecting a previous value
|
42
|
+
row_data = { "predicate_name" => predicate_name, "activated_on" => "2015-07-22", "default_presentation_sequence" => nil }
|
43
|
+
row.each_with_index do |cell, index|
|
44
|
+
row_data[header[index]] = cell unless cell.to_s.strip == ''
|
45
|
+
end
|
46
|
+
spreadsheet_data << row_data
|
47
|
+
end
|
48
|
+
spreadsheet_data
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_data_fetcher
|
52
|
+
->(document_key) { GoogleSpreadsheet.new(document_key).all_rows }
|
53
|
+
end
|
54
|
+
|
55
|
+
def convert_to_json(data)
|
56
|
+
json_array = data.map do |row|
|
57
|
+
Locabulary::Items.build(row).to_h
|
58
|
+
end
|
59
|
+
@json_data = JSON.pretty_generate("predicate_name" => predicate_name, "values" => json_array)
|
60
|
+
end
|
61
|
+
|
62
|
+
# :nocov:
|
63
|
+
# Responsible for interacting with Google Sheets and retrieiving relevant information
|
64
|
+
class GoogleSpreadsheet
|
65
|
+
attr_reader :access_token, :document_key, :session
|
66
|
+
|
67
|
+
private :session
|
68
|
+
|
69
|
+
def initialize(document_key)
|
70
|
+
@document_key = document_key
|
71
|
+
configure_oauth!
|
72
|
+
@session = GoogleDrive.login_with_oauth(access_token)
|
73
|
+
end
|
74
|
+
|
75
|
+
def configure_oauth!
|
76
|
+
client = Google::APIClient.new
|
77
|
+
auth = client.authorization
|
78
|
+
auth.client_id = client_secrets.fetch('client_id')
|
79
|
+
auth.client_secret = client_secrets.fetch('client_secret')
|
80
|
+
auth.scope = ["https://www.googleapis.com/auth/drive.readonly"]
|
81
|
+
auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
82
|
+
puts "\n Open the following URL, login with your credentials and get the authorization code \n\n #{auth.authorization_uri}\n\n"
|
83
|
+
auth.code = ask('Authorization Code: ')
|
84
|
+
auth.fetch_access_token!
|
85
|
+
@access_token = auth.access_token
|
86
|
+
end
|
87
|
+
|
88
|
+
def all_rows
|
89
|
+
session.spreadsheet_by_key(document_key).worksheets[0].rows
|
90
|
+
end
|
91
|
+
|
92
|
+
def client_secrets
|
93
|
+
@secrets ||= YAML.load(File.open(File.join(secrets_path)))
|
94
|
+
end
|
95
|
+
|
96
|
+
def secrets_path
|
97
|
+
if File.exist? File.join(File.dirname(__FILE__), '../../config/client_secrets.yml')
|
98
|
+
File.join(File.dirname(__FILE__), '../../config/client_secrets.yml')
|
99
|
+
else
|
100
|
+
File.join(File.dirname(__FILE__), '../../config/client_secrets.example.yml')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/locabulary/schema.rb
CHANGED
@@ -2,26 +2,17 @@ require 'dry/validation'
|
|
2
2
|
require 'dry/validation/schema'
|
3
3
|
|
4
4
|
module Locabulary
|
5
|
-
|
6
|
-
|
7
|
-
key(:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
value.optional(:affiliation) { |affiliation| affiliation.none? | affiliation.str? }
|
17
|
-
value.optional(:default_presentation_sequence) do |default_presentation_sequence|
|
18
|
-
default_presentation_sequence.none? | default_presentation_sequence.int?
|
19
|
-
end
|
20
|
-
value.key(:activated_on) { |activated_on| activated_on.format?(/\A\d{4}-\d{2}-\d{2}\Z/) }
|
21
|
-
value.optional(:deactivated_on) { |deactivated_on| deactivated_on.none? | deactivated_on.format?(/\A\d{4}-\d{2}-\d{2}\Z/) }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
5
|
+
# Responsible for providing a defined and clear schema for each of the locabulary items.
|
6
|
+
Schema = Dry::Validation.Schema do
|
7
|
+
key(:predicate_name).required(format?: /\A[a-z_]+\Z/)
|
8
|
+
key(:values).each do
|
9
|
+
key(:term_label).required(:str?)
|
10
|
+
optional(:description).maybe(:str?)
|
11
|
+
optional(:grouping).maybe(:str?)
|
12
|
+
optional(:affiliation).maybe(:str?)
|
13
|
+
optional(:default_presentation_sequence).maybe(:int?)
|
14
|
+
key(:activated_on).required(format?: /\A\d{4}-\d{2}-\d{2}\Z/)
|
15
|
+
optional(:deactivated_on).maybe(format?: /\A\d{4}-\d{2}-\d{2}\Z/)
|
25
16
|
end
|
26
17
|
end
|
27
18
|
end
|
data/lib/locabulary.rb
CHANGED
@@ -1,43 +1,12 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'json'
|
3
|
+
require 'locabulary/exceptions'
|
4
|
+
require 'locabulary/items'
|
3
5
|
|
4
6
|
# @since 0.1.0
|
5
7
|
module Locabulary
|
6
|
-
VERSION='0.2.0'.freeze
|
7
8
|
DATA_DIRECTORY = File.expand_path("../../data/", __FILE__).freeze
|
8
9
|
|
9
|
-
class RuntimeError < ::RuntimeError
|
10
|
-
end
|
11
|
-
|
12
|
-
class Item
|
13
|
-
include Comparable
|
14
|
-
ATTRIBUTE_NAMES = [:predicate_name, :term_label, :term_uri, :deposit_label, :description, :grouping, :affiliation, :default_presentation_sequence, :activated_on, :deactivated_on].freeze
|
15
|
-
|
16
|
-
attr_reader(*ATTRIBUTE_NAMES)
|
17
|
-
|
18
|
-
def initialize(attributes={})
|
19
|
-
ATTRIBUTE_NAMES.each do |key|
|
20
|
-
value = attributes.fetch(key) { attributes.fetch(key.to_s, nil) }
|
21
|
-
send("#{key}=", value)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
SORT_SEQUENCE_FOR_NIL = 100_000_000
|
26
|
-
def <=>(other)
|
27
|
-
value = presentation_sequence <=> other.presentation_sequence
|
28
|
-
return value unless value == 0
|
29
|
-
term_label <=> other.term_label
|
30
|
-
end
|
31
|
-
|
32
|
-
def presentation_sequence
|
33
|
-
default_presentation_sequence || SORT_SEQUENCE_FOR_NIL
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
attr_writer(*ATTRIBUTE_NAMES)
|
39
|
-
end
|
40
|
-
|
41
10
|
module_function
|
42
11
|
|
43
12
|
# @api public
|
@@ -50,25 +19,68 @@ module Locabulary
|
|
50
19
|
def active_items_for(options = {})
|
51
20
|
predicate_name = options.fetch(:predicate_name)
|
52
21
|
as_of = options.fetch(:as_of) { Date.today }
|
22
|
+
builder = Items.builder_for(predicate_name: predicate_name)
|
53
23
|
active_cache[predicate_name] ||= begin
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
24
|
+
collector = []
|
25
|
+
with_active_extraction_for(predicate_name, as_of) do |data|
|
26
|
+
collector << builder.call(data.merge('predicate_name' => predicate_name))
|
27
|
+
end
|
28
|
+
collector.sort
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @api public
|
33
|
+
# @since 0.2.0
|
34
|
+
def active_hierarchical_root(options = {})
|
35
|
+
predicate_name = options.fetch(:predicate_name)
|
36
|
+
as_of = options.fetch(:as_of) { Date.today }
|
37
|
+
builder = Items.builder_for(predicate_name: predicate_name)
|
38
|
+
active_hierarchical_root_cache[predicate_name] ||= begin
|
39
|
+
items = []
|
40
|
+
hierarchy_graph_keys = {}
|
41
|
+
top_level_slugs = Set.new
|
42
|
+
with_active_extraction_for(predicate_name, as_of) do |data|
|
43
|
+
item = builder.call(data.merge('predicate_name' => predicate_name))
|
44
|
+
items << item
|
45
|
+
top_level_slugs << item.root_slug
|
46
|
+
hierarchy_graph_keys[item.term_label] = item
|
47
|
+
end
|
48
|
+
associate_parents_and_childrens_for(hierarchy_graph_keys, items, predicate_name)
|
49
|
+
raise Exceptions::TooManyHierarchicalRootsError.new(predicate_name, top_level_slugs.to_a) if top_level_slugs.size > 1
|
50
|
+
hierarchy_graph_keys.fetch(top_level_slugs.first)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def associate_parents_and_childrens_for(hierarchy_graph_keys, items, predicate_name)
|
55
|
+
items.each do |item|
|
56
|
+
begin
|
57
|
+
hierarchy_graph_keys.fetch(item.parent_term_label).children << item unless item.parent_slugs.empty?
|
58
|
+
rescue KeyError => error
|
59
|
+
raise Exceptions::MissingHierarchicalParentError.new(predicate_name, error)
|
60
|
+
end
|
70
61
|
end
|
71
62
|
end
|
63
|
+
private :associate_parents_and_childrens_for
|
64
|
+
|
65
|
+
def with_active_extraction_for(predicate_name, as_of)
|
66
|
+
filename = filename_for_predicate_name(predicate_name: predicate_name)
|
67
|
+
json = JSON.parse(File.read(filename))
|
68
|
+
json.fetch('values').each do |data|
|
69
|
+
yield(data) if data_is_active?(data, as_of)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
private :with_active_extraction_for
|
73
|
+
|
74
|
+
def data_is_active?(data, as_of)
|
75
|
+
activated_on = Date.parse(data.fetch('activated_on'))
|
76
|
+
return false unless activated_on < as_of
|
77
|
+
deactivated_on_value = data.fetch('deactivated_on', nil)
|
78
|
+
return true if deactivated_on_value.nil?
|
79
|
+
deactivated_on = Date.parse(deactivated_on_value)
|
80
|
+
return false unless deactivated_on >= as_of
|
81
|
+
true
|
82
|
+
end
|
83
|
+
private :data_is_active?
|
72
84
|
|
73
85
|
# @api public
|
74
86
|
# @since 0.1.0
|
@@ -87,27 +99,12 @@ module Locabulary
|
|
87
99
|
active_items_for(predicate_name: predicate_name).map(&:term_label)
|
88
100
|
end
|
89
101
|
|
90
|
-
|
91
|
-
# @api public
|
92
|
-
def active_nested_labels_for(options = {})
|
93
|
-
format_active_items_for(active_labels_for(options))
|
94
|
-
end
|
95
|
-
|
96
|
-
# @api public
|
97
|
-
def properties_for_uri(options = {})
|
98
|
-
predicate_name = options.fetch(:predicate_name)
|
99
|
-
term_uri = options.fetch(:term_uri)
|
100
|
-
object = active_items_for(predicate_name: predicate_name).detect { |obj| obj.term_uri == term_uri }
|
101
|
-
return object. if object
|
102
|
-
term_uri
|
103
|
-
end
|
104
|
-
|
105
102
|
# @api private
|
106
103
|
def filename_for_predicate_name(options = {})
|
107
104
|
predicate_name = options.fetch(:predicate_name)
|
108
105
|
filename = File.join(DATA_DIRECTORY, "#{File.basename(predicate_name)}.json")
|
109
106
|
return filename if File.exist?(filename)
|
110
|
-
raise Locabulary::RuntimeError, "Unable to find predicate_name: #{predicate_name}"
|
107
|
+
raise Locabulary::Exceptions::RuntimeError, "Unable to find predicate_name: #{predicate_name}"
|
111
108
|
end
|
112
109
|
|
113
110
|
# @api private
|
@@ -116,31 +113,13 @@ module Locabulary
|
|
116
113
|
end
|
117
114
|
|
118
115
|
# @api private
|
119
|
-
def
|
120
|
-
@
|
116
|
+
def active_hierarchical_root_cache
|
117
|
+
@active_hierarchical_root_cache ||= {}
|
121
118
|
end
|
122
119
|
|
123
120
|
# @api private
|
124
|
-
def
|
125
|
-
|
126
|
-
|
127
|
-
key, value = build_key_and_value(item)
|
128
|
-
root[key] ||= []
|
129
|
-
root[key] << value
|
130
|
-
end
|
131
|
-
root
|
132
|
-
end
|
133
|
-
|
134
|
-
# @api private
|
135
|
-
def build_key_and_value(text)
|
136
|
-
text_array = text.split(/(::)/)
|
137
|
-
return text, text if text_array.size == 1
|
138
|
-
return text, text_array.last if text_array.size == 3
|
139
|
-
key = ""
|
140
|
-
(0..(text_array.size-3)).each do |index|
|
141
|
-
key << text_array[index]
|
142
|
-
end
|
143
|
-
value = text_array.last
|
144
|
-
return key, value
|
121
|
+
def reset_active_cache!
|
122
|
+
@active_cache = nil
|
123
|
+
@active_hierarchical_root_cache = nil
|
145
124
|
end
|
146
125
|
end
|
data/locabulary.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'locabulary'
|
4
|
+
require 'locabulary/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "locabulary"
|
@@ -20,12 +20,18 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.license = 'APACHE2'
|
21
21
|
|
22
22
|
spec.add_dependency "json", "~> 1.8"
|
23
|
+
spec.add_dependency "dry-configurable"
|
24
|
+
spec.add_dependency "hanami-utils"
|
23
25
|
|
24
26
|
spec.add_development_dependency "dry-validation"
|
25
27
|
spec.add_development_dependency "bundler"
|
26
|
-
spec.add_development_dependency "
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
spec.add_development_dependency "rspec-its"
|
27
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
28
31
|
spec.add_development_dependency 'google_drive'
|
29
32
|
spec.add_development_dependency 'highline'
|
30
33
|
spec.add_development_dependency "activesupport", "~>4.0"
|
34
|
+
spec.add_development_dependency "rubocop"
|
35
|
+
spec.add_development_dependency "simplecov"
|
36
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
31
37
|
end
|
data/script/update_data_files.sh
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby -U
|
2
|
+
if !ENV.key?('BUNDLE_GEMFILE')
|
3
|
+
$stderr.puts "You need to call the command via `bundle exec script/#{File.basename(__FILE__)}`"
|
4
|
+
$stderr.puts "You will also need to make sure you have valid information in ./config/client_secrets.example.yml."
|
5
|
+
abort(1)
|
6
|
+
end
|
2
7
|
|
3
|
-
|
8
|
+
require 'locabulary/json_creator'
|
4
9
|
|
5
10
|
puts "Updating Administrative Units"
|
6
|
-
json_creator = JsonCreator.new "1oBW5FCTtYXsUi8roBiMRBLFY3dXamhTqy-kiG2rqu5Q", "administrative_units"
|
11
|
+
json_creator = Locabulary::JsonCreator.new "1oBW5FCTtYXsUi8roBiMRBLFY3dXamhTqy-kiG2rqu5Q", "administrative_units"
|
7
12
|
json_creator.create_or_update
|
8
13
|
json_creator.write_to_file
|