odrl-ruby 0.1.3 → 0.1.6
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 +4 -4
- data/.rubocop.yml +5 -2
- data/Gemfile +1 -2
- data/Gemfile.lock +98 -84
- data/examples/create-nagoya-es-offer.rb +54 -0
- data/examples/nagoya-output.ttl +66 -0
- data/lib/odrl/action.rb +91 -99
- data/lib/odrl/asset.rb +63 -76
- data/lib/odrl/base.rb +14 -7
- data/lib/odrl/constraint.rb +90 -89
- data/lib/odrl/odrl/version.rb +1 -1
- data/lib/odrl/party.rb +71 -84
- data/lib/odrl/policy.rb +58 -62
- data/lib/odrl/ruby.rb +12 -13
- data/lib/odrl/rule.rb +89 -101
- metadata +6 -4
- data/examples/builder-translator-output.ttl +0 -0
- /data/examples/{output.ttl → biohackathon-output.ttl} +0 -0
data/lib/odrl/party.rb
CHANGED
@@ -1,100 +1,87 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ODRL
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
raise "If you don't indicate a predicate (assigner/assignee) we will default to assigner. This may not be what you want!"
|
29
|
-
@predicate = "http://www.w3.org/ns/odrl/2/assigner"
|
30
|
-
else
|
31
|
-
unless [PASSIGNER, PASSIGNEE].include? @predicate
|
32
|
-
raise "You didn't indicate a valid predicate (assigner/assignee) so we will default to assigner. This may not be what you want!"
|
33
|
-
@predicate = PASSIGNER
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
refinements = [refinements] unless refinements.is_a? Array
|
40
|
-
if !(refinements.first.nil?)
|
41
|
-
refinements.each do |c|
|
42
|
-
self.addRefinement(refinement: c)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
if @partOf and !(@partOf.is_a? PartyCollection) # if it exists and is the wrong type
|
47
|
-
raise "The parent collection of a Party must be of type ODRL::PaertyCollection. The provided value will be discarded"
|
48
|
-
@partOf = nil
|
49
|
-
end
|
50
|
-
|
4
|
+
class Party < Base
|
5
|
+
attr_accessor :uid, :refinements, :partOf, :predicate, :type
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
uid: nil,
|
9
|
+
refinements: nil,
|
10
|
+
partOf: nil,
|
11
|
+
predicate: nil,
|
12
|
+
type: CPARTY,
|
13
|
+
**args
|
14
|
+
)
|
15
|
+
|
16
|
+
@uid = uid
|
17
|
+
@uid ||= Base.baseURI + "#party_" + Base.getuuid
|
18
|
+
super(uid: @uid, type: type, **args)
|
19
|
+
|
20
|
+
@refinements = {}
|
21
|
+
@partOf = partOf
|
22
|
+
@predicate = predicate
|
23
|
+
|
24
|
+
if @predicate
|
25
|
+
unless [PASSIGNER, PASSIGNEE].include? @predicate
|
26
|
+
raise "You didn't indicate a valid predicate (assigner/assignee) so we will default to assigner. This may not be what you want!"
|
27
|
+
@predicate = PASSIGNER
|
51
28
|
end
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
29
|
+
else
|
30
|
+
raise "If you don't indicate a predicate (assigner/assignee) we will default to assigner. This may not be what you want!"
|
31
|
+
@predicate = "http://www.w3.org/ns/odrl/2/assigner"
|
32
|
+
end
|
33
|
+
|
34
|
+
refinements = [refinements] unless refinements.is_a? Array
|
35
|
+
unless refinements.first.nil?
|
36
|
+
refinements.each do |c|
|
37
|
+
addRefinement(refinement: c)
|
59
38
|
end
|
39
|
+
end
|
60
40
|
|
61
|
-
|
62
|
-
unless self.is_a?(PartyCollection)
|
63
|
-
raise "Party cannot be added as part of something that is not an PartyCollection"
|
64
|
-
end
|
65
|
-
unless part.is_a?(Asset)
|
66
|
-
raise "Only Parties can be added as part of PartyCollections"
|
67
|
-
end
|
68
|
-
part.partOf[self.uid] = [PPARTOF, self]
|
69
|
-
end
|
41
|
+
return unless @partOf and !(@partOf.is_a? PartyCollection) # if it exists and is the wrong type
|
70
42
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
[:refinements, :partOf].each do |connected_object_type|
|
75
|
-
next unless self.send(connected_object_type)
|
76
|
-
self.send(connected_object_type).each do |uid, typedconnection|
|
77
|
-
predicate, odrlobject = typedconnection # e.g. "refinement", RefinementObject
|
78
|
-
object = odrlobject.uid
|
79
|
-
subject = self.uid
|
80
|
-
repo = self.repository
|
81
|
-
triplify(subject, predicate, object, repo)
|
82
|
-
odrlobject.load_graph # start the cascade
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
43
|
+
raise "The parent collection of a Party must be of type ODRL::PaertyCollection. The provided value will be discarded"
|
44
|
+
@partOf = nil
|
45
|
+
end
|
86
46
|
|
87
|
-
|
88
|
-
|
89
|
-
|
47
|
+
def addRefinement(refinement: args)
|
48
|
+
raise "Refinement is not an ODRL Constraint" unless refinement.is_a?(Constraint)
|
49
|
+
|
50
|
+
refinements[refinement.uid] = [PREFINEMENT, refinement]
|
51
|
+
end
|
90
52
|
|
53
|
+
def addPart(part: args)
|
54
|
+
raise "Party cannot be added as part of something that is not an PartyCollection" unless is_a?(PartyCollection)
|
55
|
+
raise "Only Parties can be added as part of PartyCollections" unless part.is_a?(Asset)
|
56
|
+
|
57
|
+
part.partOf[uid] = [PPARTOF, self]
|
91
58
|
end
|
92
|
-
class PartyCollection < Party
|
93
59
|
|
94
|
-
|
95
|
-
|
60
|
+
def load_graph
|
61
|
+
super
|
62
|
+
# TODO: This is bad DRY!! Put the bulk of this method into the base object
|
63
|
+
%i[refinements partOf].each do |connected_object_type|
|
64
|
+
next unless send(connected_object_type)
|
65
|
+
|
66
|
+
send(connected_object_type).each do |_uid, typedconnection|
|
67
|
+
predicate, odrlobject = typedconnection # e.g. "refinement", RefinementObject
|
68
|
+
object = odrlobject.uid
|
69
|
+
subject = uid
|
70
|
+
repo = repository
|
71
|
+
triplify(subject, predicate, object, repo)
|
72
|
+
odrlobject.load_graph # start the cascade
|
96
73
|
end
|
74
|
+
end
|
97
75
|
end
|
98
76
|
|
77
|
+
def serialize(format:)
|
78
|
+
super
|
79
|
+
end
|
80
|
+
end
|
99
81
|
|
82
|
+
class PartyCollection < Party
|
83
|
+
def initialize(type: CPARTYCOLLECTION, **args)
|
84
|
+
super(type: type, **args)
|
85
|
+
end
|
86
|
+
end
|
100
87
|
end
|
data/lib/odrl/policy.rb
CHANGED
@@ -3,83 +3,79 @@
|
|
3
3
|
require_relative "odrl/version"
|
4
4
|
|
5
5
|
module ODRL
|
6
|
-
|
6
|
+
class Error < StandardError; end
|
7
7
|
|
8
|
+
class Policy < Base
|
9
|
+
attr_accessor :rules
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
def initialize(uid: nil, type: CPOLICY, **args)
|
12
|
+
@uid = uid
|
13
|
+
self.uid = Base.baseURI + "#policy_" + Base.getuuid unless @uid
|
14
|
+
super(uid: @uid, type: type, **args)
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
unless @uid
|
15
|
-
self.uid = Base.baseURI + "#policy_" + Base.getuuid
|
16
|
-
end
|
17
|
-
super(uid: @uid, type: type, **args)
|
18
|
-
|
19
|
-
@rules = Hash.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def addDuty(rule:)
|
23
|
-
uid = rule.uid
|
24
|
-
self.rules[uid] = [POBLIGATION, rule]
|
25
|
-
end
|
26
|
-
|
27
|
-
def addPermission(rule:)
|
28
|
-
uid = rule.uid
|
29
|
-
self.rules[uid] = [PPERMISSION, rule]
|
30
|
-
|
31
|
-
end
|
16
|
+
@rules = {}
|
17
|
+
end
|
32
18
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
19
|
+
def addDuty(rule:)
|
20
|
+
uid = rule.uid
|
21
|
+
rules[uid] = [POBLIGATION, rule]
|
22
|
+
end
|
37
23
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
object = ruleobject.uid
|
43
|
-
subject = self.uid
|
44
|
-
repo = self.repository
|
45
|
-
triplify(subject, predicate, object, repo)
|
46
|
-
ruleobject.load_graph # start the cascade
|
47
|
-
end
|
48
|
-
end
|
24
|
+
def addPermission(rule:)
|
25
|
+
uid = rule.uid
|
26
|
+
rules[uid] = [PPERMISSION, rule]
|
27
|
+
end
|
49
28
|
|
50
|
-
|
51
|
-
|
52
|
-
|
29
|
+
def addProhibition(rule:)
|
30
|
+
uid = rule.uid
|
31
|
+
rules[uid] = [PPROHIBITION, rule]
|
53
32
|
end
|
54
33
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
34
|
+
def load_graph
|
35
|
+
super
|
36
|
+
rules.each do |_uid, rulepair|
|
37
|
+
predicate, ruleobject = rulepair # e.g. "permission", RuleObject
|
38
|
+
object = ruleobject.uid
|
39
|
+
subject = uid
|
40
|
+
repo = repository
|
41
|
+
triplify(subject, predicate, object, repo)
|
42
|
+
ruleobject.load_graph # start the cascade
|
43
|
+
end
|
59
44
|
end
|
60
45
|
|
61
|
-
|
62
|
-
|
63
|
-
super(type: type, **args)
|
64
|
-
end
|
46
|
+
def serialize(format:)
|
47
|
+
super
|
65
48
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
class Set < Policy
|
52
|
+
def initialize(type: CSET, **args)
|
53
|
+
super(type: type, **args)
|
70
54
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
55
|
+
end
|
56
|
+
|
57
|
+
class Offer < Set
|
58
|
+
def initialize(type: COFFER, **args)
|
59
|
+
super(type: type, **args)
|
75
60
|
end
|
61
|
+
end
|
76
62
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
63
|
+
class Agreement < Set
|
64
|
+
def initialize(type: CAGREEMENT, **args)
|
65
|
+
super(type: type, **args)
|
81
66
|
end
|
82
|
-
|
67
|
+
end
|
83
68
|
|
69
|
+
class Request < Set
|
70
|
+
def initialize(type: CREQUEST, **args)
|
71
|
+
super(type: type, **args)
|
72
|
+
end
|
73
|
+
end
|
84
74
|
|
75
|
+
class Privacy < Set
|
76
|
+
def initialize(type: CPRIVACY, **args)
|
77
|
+
super(type: type, **args)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
# ====================================================
|
85
81
|
end
|
data/lib/odrl/ruby.rb
CHANGED
@@ -1,27 +1,26 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
#RDF = RDF::Vocabulary.new("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
|
1
|
+
require "linkeddata"
|
2
|
+
require "rdf/raptor"
|
5
3
|
|
4
|
+
# RDF = RDF::Vocabulary.new("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
|
6
5
|
|
7
6
|
RDFS = RDF::Vocabulary.new("http://www.w3.org/2000/01/rdf-schema#")
|
8
7
|
DCAT = RDF::Vocabulary.new("http://www.w3.org/ns/dcat#")
|
9
8
|
DC = RDF::Vocabulary.new("http://purl.org/dc/elements/1.1/")
|
10
9
|
DCT = RDF::Vocabulary.new("http://purl.org/dc/terms/")
|
11
10
|
FUND = RDF::Vocabulary.new("http://vocab.ox.ac.uk/projectfunding#")
|
12
|
-
SKOS =
|
13
|
-
ODRLV =
|
11
|
+
SKOS = RDF::Vocabulary.new("http://www.w3.org/2004/02/skos/core#")
|
12
|
+
ODRLV = RDF::Vocabulary.new("http://www.w3.org/ns/odrl/2/")
|
14
13
|
OBO = RDF::Vocabulary.new("http://purl.obolibrary.org/obo/")
|
15
14
|
XSD = RDF::Vocabulary.new("http://www.w3.org/2001/XMLSchema#")
|
16
15
|
SCHEMA = RDF::Vocabulary.new("https://schema.org/")
|
17
16
|
|
18
|
-
require_relative "
|
19
|
-
require_relative "
|
20
|
-
require_relative "
|
21
|
-
require_relative "
|
22
|
-
require_relative "
|
23
|
-
require_relative "
|
24
|
-
require_relative "
|
17
|
+
require_relative "base"
|
18
|
+
require_relative "action"
|
19
|
+
require_relative "asset"
|
20
|
+
require_relative "constraint"
|
21
|
+
require_relative "party"
|
22
|
+
require_relative "policy"
|
23
|
+
require_relative "rule"
|
25
24
|
|
26
25
|
module ODRL
|
27
26
|
end
|
data/lib/odrl/rule.rb
CHANGED
@@ -5,124 +5,112 @@ require_relative "odrl/version"
|
|
5
5
|
# require "ODRL::Constraint"
|
6
6
|
|
7
7
|
module ODRL
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
constraints = [constraints] unless constraints.is_a? Array
|
40
|
-
if !constraints.first.nil?
|
41
|
-
constraints.each do |c|
|
42
|
-
self.addConstraint(constraint: c)
|
43
|
-
end
|
44
|
-
end
|
8
|
+
class Rule < Base
|
9
|
+
attr_accessor :uid, :constraints, :assets, :predicate, :type, :action, :assigner, :assignee
|
10
|
+
|
11
|
+
def initialize(
|
12
|
+
uid: nil,
|
13
|
+
constraints: nil,
|
14
|
+
assets: nil,
|
15
|
+
predicate: nil,
|
16
|
+
action: nil,
|
17
|
+
assigner: nil,
|
18
|
+
assignee: nil,
|
19
|
+
type: CRULE,
|
20
|
+
**args
|
21
|
+
)
|
22
|
+
@uid = uid
|
23
|
+
|
24
|
+
@uid ||= Base.baseURI + "#rule_" + Base.getuuid
|
25
|
+
super(uid: @uid, type: type, **args)
|
26
|
+
|
27
|
+
@constraints = {}
|
28
|
+
@assets = {}
|
29
|
+
@assigner = {}
|
30
|
+
@assignee = {}
|
31
|
+
@action = {}
|
32
|
+
|
33
|
+
assets = [assets] unless assets.is_a? Array
|
34
|
+
unless assets.first.nil?
|
35
|
+
assets.each do |c|
|
36
|
+
addAsset(asset: c)
|
45
37
|
end
|
38
|
+
end
|
39
|
+
constraints = [constraints] unless constraints.is_a? Array
|
40
|
+
return if constraints.first.nil?
|
46
41
|
|
42
|
+
constraints.each do |c|
|
43
|
+
addConstraint(constraint: c)
|
44
|
+
end
|
45
|
+
end
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
raise "Asset is not an ODRL Asset"
|
51
|
-
else
|
52
|
-
uid = asset.uid
|
53
|
-
self.assets[uid] = [PASSET, asset]
|
54
|
-
end
|
55
|
-
end
|
47
|
+
def addAsset(asset:)
|
48
|
+
raise "Asset is not an ODRL Asset" unless asset.is_a?(Asset)
|
56
49
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
else
|
61
|
-
self.constraints[constraint.uid] = [PCONSTRAINT, constraint]
|
62
|
-
end
|
63
|
-
end
|
50
|
+
uid = asset.uid
|
51
|
+
assets[uid] = [PASSET, asset]
|
52
|
+
end
|
64
53
|
|
65
|
-
|
66
|
-
|
67
|
-
raise "Action is not an ODRL Action"
|
68
|
-
else
|
69
|
-
self.action[action.uid] = [PACTION, action]
|
70
|
-
end
|
71
|
-
end
|
54
|
+
def addConstraint(constraint:)
|
55
|
+
raise "Constraint is not an ODRL Constraint" unless constraint.is_a?(Constraint)
|
72
56
|
|
73
|
-
|
74
|
-
|
75
|
-
raise "Assigner is not an ODRL Party"
|
76
|
-
else
|
77
|
-
self.assigner[party.uid] = [PASSIGNER, party]
|
78
|
-
end
|
79
|
-
end
|
57
|
+
constraints[constraint.uid] = [PCONSTRAINT, constraint]
|
58
|
+
end
|
80
59
|
|
81
|
-
|
82
|
-
|
83
|
-
raise "Asigner is not an ODRL Party"
|
84
|
-
else
|
85
|
-
self.assignee[party.uid] = [PASSIGNEE, party]
|
86
|
-
end
|
87
|
-
end
|
60
|
+
def addAction(action:)
|
61
|
+
raise "Action is not an ODRL Action" unless action.is_a?(Action)
|
88
62
|
|
89
|
-
|
90
|
-
|
91
|
-
[:constraints, :assets, :action, :assigner, :assignee].each do |connected_object_type|
|
92
|
-
next unless self.send(connected_object_type)
|
93
|
-
self.send(connected_object_type).each do |uid, typedconnection|
|
94
|
-
predicate, odrlobject = typedconnection # e.g. "action", ActionObject
|
95
|
-
object = odrlobject.uid
|
96
|
-
subject = self.uid
|
97
|
-
repo = self.repository
|
98
|
-
triplify(subject, predicate, object, repo)
|
99
|
-
odrlobject.load_graph # start the cascade
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
63
|
+
self.action[action.uid] = [PACTION, action]
|
64
|
+
end
|
103
65
|
|
104
|
-
|
105
|
-
|
106
|
-
|
66
|
+
def addAssigner(party:)
|
67
|
+
raise "Assigner is not an ODRL Party" unless party.is_a?(Party)
|
68
|
+
|
69
|
+
assigner[party.uid] = [PASSIGNER, party]
|
107
70
|
end
|
108
71
|
|
72
|
+
def addAssignee(party:)
|
73
|
+
raise "Asigner is not an ODRL Party" unless party.is_a?(Party)
|
109
74
|
|
110
|
-
|
111
|
-
def initialize(predicate: PPERMISSION, type: CPERMISSION, **args)
|
112
|
-
super(predicate: predicate, type: type, **args)
|
113
|
-
end
|
75
|
+
assignee[party.uid] = [PASSIGNEE, party]
|
114
76
|
end
|
115
77
|
|
116
|
-
|
117
|
-
|
118
|
-
|
78
|
+
def load_graph
|
79
|
+
super
|
80
|
+
%i[constraints assets action assigner assignee].each do |connected_object_type|
|
81
|
+
next unless send(connected_object_type)
|
82
|
+
|
83
|
+
send(connected_object_type).each do |_uid, typedconnection|
|
84
|
+
predicate, odrlobject = typedconnection # e.g. "action", ActionObject
|
85
|
+
object = odrlobject.uid
|
86
|
+
subject = uid
|
87
|
+
repo = repository
|
88
|
+
triplify(subject, predicate, object, repo)
|
89
|
+
odrlobject.load_graph # start the cascade
|
119
90
|
end
|
91
|
+
end
|
120
92
|
end
|
121
93
|
|
122
|
-
|
123
|
-
|
124
|
-
super(predicate: predicate, type: type, **args)
|
125
|
-
end
|
94
|
+
def serialize(format:)
|
95
|
+
super
|
126
96
|
end
|
97
|
+
end
|
127
98
|
|
99
|
+
class Permission < Rule
|
100
|
+
def initialize(predicate: PPERMISSION, type: CPERMISSION, **args)
|
101
|
+
super(predicate: predicate, type: type, **args)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Duty < Rule
|
106
|
+
def initialize(predicate: PDUTY, type: CDUTY, **args)
|
107
|
+
super(predicate: predicate, type: type, **args)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class Prohibition < Rule
|
112
|
+
def initialize(predicate: PPROHIBITION, type: CPROHIBITION, **args)
|
113
|
+
super(predicate: predicate, type: type, **args)
|
114
|
+
end
|
115
|
+
end
|
128
116
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: odrl-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Wilkinson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: builds ODRL files nicely.
|
14
14
|
email:
|
@@ -26,9 +26,10 @@ files:
|
|
26
26
|
- Rakefile
|
27
27
|
- bin/console
|
28
28
|
- bin/setup
|
29
|
-
- examples/
|
29
|
+
- examples/biohackathon-output.ttl
|
30
30
|
- examples/create-biohackathon-offer.rb
|
31
|
-
- examples/
|
31
|
+
- examples/create-nagoya-es-offer.rb
|
32
|
+
- examples/nagoya-output.ttl
|
32
33
|
- launch.json
|
33
34
|
- lib/odrl/action.rb
|
34
35
|
- lib/odrl/asset.rb
|
@@ -47,6 +48,7 @@ metadata:
|
|
47
48
|
homepage_uri: https://example.org
|
48
49
|
source_code_uri: https://github.com/markwilkinson/ODRL-RUBY
|
49
50
|
changelog_uri: https://github.com/markwilkinson/ODRL-RUBY/blob/master/CHANGELOG.md
|
51
|
+
documentation_uri: https://www.rubydoc.info/gems/odrl-ruby/
|
50
52
|
post_install_message:
|
51
53
|
rdoc_options: []
|
52
54
|
require_paths:
|
File without changes
|
File without changes
|