active-triples 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac814924c8de3fbbc7c606f086d17dbaae387fc9
4
- data.tar.gz: 80686fffd9084847077ffd12167279ee7becb17e
3
+ metadata.gz: c8f2271397f8aecc1c96f8bd3cf63744e87e0989
4
+ data.tar.gz: 25d4b23e7404fafd3c437e4cf0ff4de54f9c7c54
5
5
  SHA512:
6
- metadata.gz: f81545cb8bd68a532d67ea52a4d0b011be195c76af069d77e2f4a21d012c76a3a853819e9ebc7745918561dd67fad6bab40589173eb2219e915d80aa20e6429c
7
- data.tar.gz: 590fedb6315223dfb2485415c8d345dc8928f2cadf0b5c36ca3675d50b067cc32a0843a1cb89af24749eea81691d7f0f881f14716c9caac7069e05cbd43b16b5
6
+ metadata.gz: b4645aa5fc8dd320fe19fe46268b500533fad11836093dcd8ad594b7b9052f5f531e61332b625a4284ebae92b8de2651ca29e8aa0c9833b5a5a0a9e635a3a75a
7
+ data.tar.gz: fed0f9f047b36fd5f84bb231e83f021da0aa27991239697b58c173df75685b4a30a4a5715095cf538d709fd4c4336debf93b1814df0b73d0be0a3fc11a01becf
data/AUTHORS CHANGED
@@ -1,2 +1,2 @@
1
- Tom Johnson (thomas.johnson@oregonstate.edu)
2
- Trey Terrell
1
+ * Tom Johnson (thomas.johnson@oregonstate.edu)
2
+ * Trey Terrell
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/README.md CHANGED
@@ -1,38 +1,152 @@
1
- ActiveTriples
2
- ==============
1
+ Description
2
+ -----------
3
3
 
4
4
  [![Build Status](https://travis-ci.org/no-reply/ActiveTriples.png?branch=master)](https://travis-ci.org/no-reply/ActiveTriples)
5
5
 
6
- Modeling RDF graphs in Ruby.
6
+ An ActiveModel-like interface for RDF data. Models graphs as Resources with property/attribute configuration, accessors, and other methods to support Linked Data in a Ruby/Rails enviornment.
7
+
8
+ This library was extracted from work on [ActiveFedora](https://github.com/projecthydra/active_fedora). It is closely related to (and borrows some syntax from) [Spira](https://github.com/ruby-rdf/spira), but does some important things differently.
9
+
10
+ Installation
11
+ ------------
12
+
13
+ Add `gem "active-triples"` to your Gemfile and run `bundle`.
14
+
15
+ Or install manually with `gem install active-triples`.
16
+
17
+ Defining Resource Models
18
+ ------------------------
19
+
20
+ The core class of ActiveTriples is ActiveTriples::Resource. You can subclass this to create ActiveModel-like classes that represent a node in an RDF graph, and its surrounding statements. Resources implement all the functionality of an RDF::Graph. You can manipulate them by adding or deleting statements, query, serialize, and load arbitrary RDF.
7
21
 
8
- How to Use
9
- -----------
10
22
 
11
23
  ```ruby
12
24
  class Thing < ActiveTriples::Resource
13
25
  configure :type => RDF::OWL.Thing, :base_uri => 'http://example.org/things#'
14
26
  property :title, :predicate => RDF::DC.title
15
27
  property :description, :predicate => RDF::DC.description
16
- property :creator, :predicate => RDF::DC.creator, :class_name => 'Person'
17
28
  end
18
29
 
19
30
  obj = Thing.new('123')
20
31
  obj.title = 'Resource'
21
- obj.description = 'A resource in an RDF graph.'
32
+ obj.description = 'A resource.'
33
+ obj.dump :ntriples # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource.\" .\n"
34
+ ```
35
+ URI and bnode values are built out as Resources when accessed, and a model class can be configured on individual properties.
22
36
 
23
- obj.dump :ntriples
24
- # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource in an RDF graph.\" .\n"
37
+ ```ruby
38
+ Thing.property :creator, :predicate => RDF::DC.creator, :class_name => 'Person'
25
39
 
26
40
  class Person < ActiveTriples::Resource
27
41
  configure :type => RDF::FOAF.Person, :base_uri => 'http://example.org/people#'
28
42
  property :name, :predicate => RDF::FOAF.name
29
43
  end
30
44
 
31
- obj.creator = Person.new
32
- obj.creator
45
+ obj_2 = Thing.new('2')
46
+ obj_2.creator = Person.new
47
+ obj_2.creator
33
48
  # => [#<Person:0x3fbe84ac9234(default)>]
34
49
 
35
- obj.creator.first.name = 'Herman Melville'
36
- obj.dump :ntriples
37
- # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource in an RDF graph.\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/creator> _:g70087502237940 .\n_:g70087502237940 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n"
38
- ```
50
+ obj_2.creator.first.name = 'Herman Melville'
51
+ obj_2.dump :ntriples # => "<http://example.org/things#2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#2> <http://purl.org/dc/terms/creator> _:g70263220218800 .\n_:g70263220218800 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n_:g70263220218800 <http://xmlns.com/foaf/0.1/name> \"Herman Melville\" .\n"
52
+ ```
53
+
54
+ Open Model
55
+ -----------
56
+
57
+ A Resource lets you handle data as a graph, independent of whether it is defined in the model. This is important for working in a Linked Data context, where you will want access to data you may not have known about when your models were written.
58
+
59
+ ```ruby
60
+ related = Thing.new
61
+
62
+ related << RDF::Statement(related, RDF::DC.relation, obj)
63
+ related << RDF::Statement(related, RDF::DC.subject, 'ActiveTriples')
64
+
65
+ related.query(:subject => related, :predicate => RDF::DC.relation).each_statement {|s,p,o| puts o}
66
+ # => http://example.org/things#123
67
+ related.query(:subject => subject, :predicate => RDF::DC.relation).each_statement {|s,p,o| puts o}
68
+ # => http://example.org/things#123
69
+ ```
70
+
71
+ Any operation you can run against an RDF::Graph works with Resources, too. Or you can use generic setters and getters with URI predicates:
72
+
73
+ ```ruby
74
+ related.set_value(RDF::DC.relation, obj)
75
+ related.set_value(RDF::DC.subject, 'ActiveTriples')
76
+
77
+ related.get_values(RDF::DC.relation) # => [#<Thing:0x3f949c6a2294(default)>]
78
+ related.get_values(RDF::DC.subject) # => ["ActiveTriples"]
79
+ ```
80
+
81
+ Some convienience methods provide support for handling data from web sources:
82
+ * `fetch` loads data from the Resource's #rdf_subject URI
83
+ * `rdf_label` queries across common (& configured) label fields and returning the best match
84
+
85
+ ```ruby
86
+ require 'linkeddata' # to support various serializations
87
+
88
+ osu = ActiveTriples::Resource.new 'http://dbpedia.org/resource/Oregon_State_University'
89
+ osu.fetch
90
+
91
+ osu.rdf_label => => ["Oregon State University", "Oregon State University", "Université d'État de l'Oregon", "Oregon State University", "Oregon State University", "オレゴン州立大学", "Universidad Estatal de Oregón", "Oregon State University", "俄勒岡州立大學", "Universidade do Estado do Oregon"]
92
+ ```
93
+
94
+ Typed Data
95
+ -----------
96
+
97
+ Typed literals are handled natively through Ruby types and [RDF::Literal](https://github.com/ruby-rdf/rdf/tree/develop/lib/rdf/model/literal). There is no need to register a specific type for a property, simply pass the setter the appropriate typed data. See the examples in the RDF::Literal documentation for futher information about supported datatypes.
98
+
99
+ ```ruby
100
+ Thing.property :date, :predicate => RDF::DC.date
101
+
102
+ my_thing = Thing.new
103
+ my_thing.date = Date.today
104
+
105
+ puts my_thing.dump :ntriples
106
+ # _:g70072864570340 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .
107
+ # _:g70072864570340 <http://purl.org/dc/terms/date> "2014-06-19Z"^^<http://www.w3.org/2001/XMLSchema#date> .
108
+ ```
109
+
110
+ Data is cast back to the appropriate class when it is accessed.
111
+
112
+ ```ruby
113
+ my_thing.date
114
+ # => [Thu, 19 Jun 2014]
115
+ ```
116
+
117
+ Note that you can mix types on a single property.
118
+
119
+ ```ruby
120
+ my_thing.date << DateTime.now
121
+ my_thing.date << "circa 2014"
122
+ my_thing.date
123
+ # => [Thu, 19 Jun 2014, Thu, 19 Jun 2014 11:39:21 -0700, "circa 2014"]
124
+
125
+ puts my_thing.dump :ntriples
126
+ # _:g70072864570340 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .
127
+ # _:g70072864570340 <http://purl.org/dc/terms/date> "2014-06-19Z"^^<http://www.w3.org/2001/XMLSchema#date> .
128
+ # _:g70072864570340 <http://purl.org/dc/terms/date> "2014-06-19T11:39:21-07:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
129
+ # _:g70072864570340 <http://purl.org/dc/terms/date> "circa 2014" .
130
+ ```
131
+
132
+ Repositories and Persistence
133
+ -----------------------------
134
+
135
+ Contributing
136
+ -------------
137
+
138
+ Please observe the following guidelines:
139
+
140
+ - Do your work in a feature branch based on ```master``` and rebase before submitting a pull request.
141
+ - Write tests for your contributions.
142
+ - Document every method you add using YARD annotations. (_Note: Annotations are sparse in the existing codebase, help us fix that!_)
143
+ - Organize your commits into logical units.
144
+ - Don't leave trailing whitespace (i.e. run ```git diff --check``` before committing).
145
+ - Use [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) commit messages.
146
+
147
+ By contributing to ActiveTriples, you agree to dedicate all copyright interest over submitted work to the public domain (see the included ```WAIVER``` and ```LICENSE``` files). For substantial contributions, you may be asked to submit a formal disclaimer of your (and/or your employer's) copyright interest in the software.
148
+
149
+ License
150
+ --------
151
+
152
+ This is free and unencumbered public domain software. For more information, see http://unlicense.org/ or the accompanying ```LICENSE``` file.
data/WAIVER ADDED
@@ -0,0 +1,5 @@
1
+ I dedicate any and all copyright interest in this software to the
2
+ public domain. I make this dedication for the benefit of the public at
3
+ large and to the detriment of my heirs and successors. I intend this
4
+ dedication to be an overt act of relinquishment in perpetuity of all
5
+ present and future rights to this software under copyright law.
@@ -22,8 +22,10 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency('rdoc')
24
24
  s.add_development_dependency('rspec')
25
+ s.add_development_dependency('guard-rspec')
25
26
  s.add_development_dependency('webmock')
26
27
  s.add_development_dependency('nokogiri')
28
+ s.add_development_dependency('pragmatic_context', '~> 0.1.2')
27
29
 
28
30
  s.files = `git ls-files`.split("\n")
29
31
  s.test_files = `git ls-files -- {spec}/*`.split("\n")
@@ -8,7 +8,7 @@ module ActiveTriples
8
8
  #
9
9
  # Define properties at the class level with:
10
10
  #
11
- # configure base_uri: "http://oregondigital.org/resource/", repository: :parent
11
+ # configure base_uri: "http://oregondigital.org/resource/", repository: :default
12
12
  # Available properties are base_uri, rdf_label, type, and repository
13
13
  module Configurable
14
14
  extend Deprecation
@@ -25,6 +25,8 @@ module ActiveTriples
25
25
  nil
26
26
  end
27
27
 
28
+ ##
29
+ # @deprecated use `configure type:` instead.
28
30
  def rdf_type(value)
29
31
  Deprecation.warn Configurable, "rdf_type is deprecated and will be removed in active-fedora 8.0.0. Use configure type: instead.", caller
30
32
  configure type: value
@@ -34,8 +36,21 @@ module ActiveTriples
34
36
  :parent
35
37
  end
36
38
 
37
- # API method for configuring class properties an RDF Resource may need.
38
- # This is an alternative to overriding the methods extended with this module.
39
+ ##
40
+ # API for configuring class properties on a Resource. This is an
41
+ # alternative to overriding the methods in this module.
42
+ #
43
+ # Can configure the following values:
44
+ # - base_uri (allows passing slugs to the Resource initializer
45
+ # in place of fully qualified URIs)
46
+ # - rdf_label (overrides default label predicates)
47
+ # - type (a default rdf:type to include when initializing a
48
+ # new Resource)
49
+ # - repository (the target persist location to for the Resource)
50
+ #
51
+ # configure base_uri: "http://oregondigital.org/resource/", repository: :default
52
+ #
53
+ # @param options [Hash]
39
54
  def configure(options = {})
40
55
  {
41
56
  base_uri: options[:base_uri],
@@ -110,6 +110,13 @@ module ActiveTriples
110
110
  super
111
111
  end
112
112
 
113
+ protected
114
+ # Clear out any old assertions in the repository about this node or statement
115
+ # thus preparing to receive the updated assertions.
116
+ def erase_old_resource
117
+ RDF::List.new(rdf_subject, repository).clear
118
+ end
119
+
113
120
  private
114
121
  def attributes_to_list(value, klass)
115
122
  value.each do |entry|
@@ -16,6 +16,7 @@ module ActiveTriples
16
16
  end
17
17
 
18
18
  def class_name
19
+ raise "class_name for #{term} is a #{@class_name.class}; must be a class" unless @class_name.kind_of? Class or @class_name.kind_of? String
19
20
  if @class_name.kind_of?(String)
20
21
  begin
21
22
  new_class = @class_name.constantize
@@ -1,4 +1,3 @@
1
- require 'deprecation'
2
1
  require 'active_support/core_ext/hash'
3
2
 
4
3
  module ActiveTriples
@@ -11,15 +10,7 @@ module ActiveTriples
11
10
  #
12
11
  # property :title, predicate: RDF::DC.title, class_name: ResourceClass
13
12
  #
14
- # or with the 'old' style:
15
- #
16
- # map_predicates do |map|
17
- # map.title(in: RDF::DC)
18
- # end
19
- #
20
- # You can pass a block to either to set index behavior.
21
13
  module Properties
22
- extend Deprecation
23
14
  attr_accessor :config
24
15
 
25
16
  ##
@@ -35,6 +26,11 @@ module ActiveTriples
35
26
  register_property(name)
36
27
  end
37
28
 
29
+ ##
30
+ # Returns the properties registered to the class and their
31
+ # configurations.
32
+ #
33
+ # @return [ActiveSupport::HashWithIndifferentAccess{String => ActiveTriples::NodeConfig}]
38
34
  def config
39
35
  @config ||= if superclass.respond_to? :config
40
36
  superclass.config.dup
@@ -46,11 +42,23 @@ module ActiveTriples
46
42
  alias_method :properties, :config
47
43
  alias_method :properties=, :config=
48
44
 
45
+ ##
46
+ # Given a property name or a predicate, return the configuration
47
+ # for the matching property.
48
+ #
49
+ # @param term [#to_sym, RDF::Resource] a property name to predicate
50
+ #
51
+ # @return [ActiveTriples::NodeConfig]
49
52
  def config_for_term_or_uri(term)
50
53
  return config[term.to_sym] unless term.kind_of? RDF::Resource
51
54
  config.each { |k, v| return v if v.predicate == term.to_uri }
52
55
  end
53
56
 
57
+ ##
58
+ # List the property names registered to the class.
59
+ #
60
+ # @return [Array<Symbol>] list of the symbolized names of registered
61
+ # properties
54
62
  def fields
55
63
  properties.keys.map(&:to_sym)
56
64
  end
@@ -59,7 +67,9 @@ module ActiveTriples
59
67
 
60
68
  ##
61
69
  # Private method for creating accessors for a given property.
62
- # @param [#to_s] name Name of the accessor to be created, get/set_value is called on the resource using this.
70
+ #
71
+ # @param [#to_s] name Name of the accessor to be created,
72
+ # get/set_value is called on the resource using this.
63
73
  def register_property(name)
64
74
  parent = Proc.new{self}
65
75
  # parent = Proc.new{resource} if self < ActiveFedora::Datastream
@@ -70,27 +80,5 @@ module ActiveTriples
70
80
  instance_eval(&parent).get_values(name.to_sym)
71
81
  end
72
82
  end
73
-
74
- public
75
- # Mapper is for backwards compatibility with ActiveFedora::RDFDatastream
76
- class Mapper
77
- attr_accessor :parent
78
- def initialize(parent)
79
- @parent = parent
80
- end
81
- def method_missing(name, *args, &block)
82
- properties = args.first || {}
83
- vocab = properties.delete(:in)
84
- to = properties.delete(:to) || name
85
- predicate = vocab.send(to)
86
- parent.property(name, properties.merge(predicate: predicate), &block)
87
- end
88
- end
89
- def map_predicates
90
- Deprecation.warn Properties, "map_predicates is deprecated and will be removed in active-fedora 8.0.0. Use property :name, predicate: predicate instead.", caller
91
- mapper = Mapper.new(self)
92
- yield(mapper)
93
- end
94
-
95
83
  end
96
84
  end
@@ -24,8 +24,7 @@ module ActiveTriples
24
24
  extend Configurable
25
25
  extend Properties
26
26
  extend Deprecation
27
- extend ActiveModel::Naming
28
- include ActiveModel::Conversion
27
+ include ActiveModel::Model
29
28
  include ActiveModel::Serialization
30
29
  include ActiveModel::Serializers::JSON
31
30
  include NestedAttributes
@@ -37,13 +36,23 @@ module ActiveTriples
37
36
  end
38
37
 
39
38
  ##
40
- # Adapter for a consistent interface for creating a new node from a URI.
41
- # Similar functionality should exist in all objects which can become a node.
39
+ # Adapter for a consistent interface for creating a new Resource
40
+ # from a URI. Similar functionality should exist in all objects
41
+ # which can become a Resource.
42
+ #
43
+ # @param uri [#to_uri, String]
44
+ # @param vals values to pass as arguments to ::new
45
+ #
46
+ # @return [ActiveTriples::Resource] a Resource with
42
47
  def from_uri(uri,vals=nil)
43
48
  new(uri, vals)
44
49
  end
45
50
  end
46
51
 
52
+ ##
53
+ # Specifies whether the object is currently writable.
54
+ #
55
+ # @return [true, false]
47
56
  def writable?
48
57
  !frozen?
49
58
  end
@@ -68,8 +77,14 @@ module ActiveTriples
68
77
  self.get_values(:type) << self.class.type if self.class.type.kind_of?(RDF::URI) && type.empty?
69
78
  end
70
79
 
80
+ ##
81
+ # Returns the current object.
82
+ #
83
+ # @deprecated redundant, simply returns self.
84
+ #
85
+ # @return [self]
71
86
  def graph
72
- Deprecation.warn Resource, "graph is redundant & deprecated. It will be removed in active-fedora 8.0.0.", caller
87
+ Deprecation.warn Resource, "graph is redundant & deprecated. It will be removed in ActiveTriples 0.2.0.", caller
73
88
  self
74
89
  end
75
90
 
@@ -112,28 +127,51 @@ module ActiveTriples
112
127
  end
113
128
  end
114
129
  end
130
+
131
+ ##
132
+ # Returns a serialized string representation of self.
133
+ # Extends the base implementation builds a JSON-LD context if the
134
+ # specified format is :jsonld and a context is provided by
135
+ # #jsonld_context
136
+ #
137
+ # @see RDF::Enumerable#dump
138
+ #
139
+ # @param args [Array<Object>]
140
+ # @return [String]
141
+ def dump(*args)
142
+ if args.first == :jsonld and respond_to?(:jsonld_context)
143
+ args << {} unless args.last.is_a?(Hash)
144
+ args.last[:context] ||= jsonld_context
145
+ end
146
+ super
147
+ end
115
148
 
149
+ ##
150
+ # @return [RDF::URI, RDF::Node] a URI or Node which the resource's
151
+ # properties are about.
116
152
  def rdf_subject
117
153
  @rdf_subject ||= RDF::Node.new
118
154
  end
119
-
155
+ alias_method :to_term, :rdf_subject
156
+
157
+ ##
158
+ # A string identifier for the resource
120
159
  def id
121
160
  node? ? nil : rdf_subject.to_s
122
161
  end
123
-
162
+
124
163
  def node?
125
164
  return true if rdf_subject.kind_of? RDF::Node
126
165
  false
127
166
  end
128
167
 
129
- def to_term
130
- rdf_subject
131
- end
132
-
168
+ ##
169
+ # @return [String, nil] the base URI the resource will use when
170
+ # setting its subject. `nil` if none is used.
133
171
  def base_uri
134
172
  self.class.base_uri
135
173
  end
136
-
174
+
137
175
  def type
138
176
  self.get_values(:type).to_a.map{|x| x.rdf_subject}
139
177
  end
@@ -144,8 +182,8 @@ module ActiveTriples
144
182
  end
145
183
 
146
184
  ##
147
- # Look for labels in various default fields, prioritizing
148
- # configured label fields
185
+ # Looks for labels in various default fields, prioritizing
186
+ # configured label fields.
149
187
  def rdf_label
150
188
  labels = Array(self.class.rdf_label)
151
189
  labels += default_labels
@@ -156,12 +194,26 @@ module ActiveTriples
156
194
  node? ? [] : [rdf_subject.to_s]
157
195
  end
158
196
 
197
+ ##
198
+ # Lists fields registered as properties on the object.
199
+ #
200
+ # @return [Array<Symbol>] the list of registered properties.
159
201
  def fields
160
202
  properties.keys.map(&:to_sym).reject{|x| x == :type}
161
203
  end
162
204
 
163
205
  ##
164
- # Load data from URI
206
+ # Load data from the #rdf_subject URI. Retrieved data will be
207
+ # parsed into the Resource's graph from available RDF::Readers
208
+ # and available from property accessors if if predicates are
209
+ # registered.
210
+ #
211
+ # osu = ActiveTriples::Resource.new('http://dbpedia.org/resource/Oregon_State_University')
212
+ # osu.fetch
213
+ # osu.rdf_label.first
214
+ # # => "Oregon State University"
215
+ #
216
+ # @return [ActiveTriples::Resource] self
165
217
  def fetch
166
218
  load(rdf_subject)
167
219
  self
@@ -169,16 +221,16 @@ module ActiveTriples
169
221
 
170
222
  def persist!
171
223
  raise "failed when trying to persist to non-existant repository or parent resource" unless repository
172
- repository.delete [rdf_subject,nil,nil] unless node?
173
- if node?
174
- repository.statements.each do |statement|
175
- repository.send(:delete_statement, statement) if statement.subject == rdf_subject
176
- end
177
- end
224
+ erase_old_resource
178
225
  repository << self
179
226
  @persisted = true
180
227
  end
181
228
 
229
+ ##
230
+ # Indicates if the resource is persisted.
231
+ #
232
+ # @see #persist
233
+ # @return [true, false]
182
234
  def persisted?
183
235
  @persisted ||= false
184
236
  return (@persisted and parent.persisted?) if parent
@@ -187,6 +239,8 @@ module ActiveTriples
187
239
 
188
240
  ##
189
241
  # Repopulates the graph from the repository or parent resource.
242
+ #
243
+ # @return [true, false]
190
244
  def reload
191
245
  @term_cache ||= {}
192
246
  if self.class.repository == :parent
@@ -280,6 +334,10 @@ module ActiveTriples
280
334
  end
281
335
  alias_method :destroy!, :destroy
282
336
 
337
+ ##
338
+ # Indicates if the Resource has been destroyed.
339
+ #
340
+ # @return [true, false]
283
341
  def destroyed?
284
342
  @destroyed ||= false
285
343
  end
@@ -290,12 +348,16 @@ module ActiveTriples
290
348
  end
291
349
  end
292
350
 
351
+ ##
352
+ # Indicates if the record is 'new' (has not yet been persisted).
353
+ #
354
+ # @return [true, false]
293
355
  def new_record?
294
356
  not persisted?
295
357
  end
296
358
 
297
359
  ##
298
- # @return [String] the string to index in solr
360
+ # @return [String] the string representation of the resource
299
361
  def solrize
300
362
  node? ? rdf_label : rdf_subject.to_s
301
363
  end
@@ -308,22 +370,57 @@ module ActiveTriples
308
370
  @marked_for_destruction
309
371
  end
310
372
 
311
- private
373
+ protected
374
+
375
+ #Clear out any old assertions in the repository about this node or statement
376
+ # thus preparing to receive the updated assertions.
377
+ def erase_old_resource
378
+ if node?
379
+ repository.statements.each do |statement|
380
+ repository.send(:delete_statement, statement) if statement.subject == rdf_subject
381
+ end
382
+ else
383
+ repository.delete [rdf_subject, nil, nil]
384
+ end
385
+ end
312
386
 
387
+ private
388
+
389
+ ##
390
+ # Returns the properties registered and their configurations.
391
+ #
392
+ # @return [ActiveSupport::HashWithIndifferentAccess{String => ActiveTriples::NodeConfig}]
313
393
  def properties
314
394
  self.singleton_class.properties
315
395
  end
316
396
 
397
+ ##
398
+ # List of RDF predicates registered as properties on the object.
399
+ #
400
+ # @return [Array<RDF::URI>]
317
401
  def registered_predicates
318
402
  properties.values.map { |config| config.predicate }
319
403
  end
320
404
 
405
+ ##
406
+ # List of RDF predicates used in the Resource's triples, but not
407
+ # mapped to any property or accessor methods.
408
+ #
409
+ # @return [Array<RDF::URI>]
321
410
  def unregistered_predicates
322
411
  preds = registered_predicates
323
412
  preds << RDF.type
324
413
  predicates.select { |p| !preds.include? p }
325
414
  end
326
415
 
416
+ ##
417
+ # Given a predicate which has been registered to a property,
418
+ # returns the name of the matching property.
419
+ #
420
+ # @param predicate [RDF::URI]
421
+ #
422
+ # @return [String, nil] the name of the property mapped to the
423
+ # predicate provided
327
424
  def property_for_predicate(predicate)
328
425
  properties.each do |property, values|
329
426
  return property if values[:predicate] == predicate
@@ -342,6 +439,9 @@ module ActiveTriples
342
439
  ##
343
440
  # Return the repository (or parent) that this resource should
344
441
  # write to when persisting.
442
+ #
443
+ # @return [RDF::Repository, ActiveTriples::Resource] the target
444
+ # repository
345
445
  def repository
346
446
  @repository ||=
347
447
  if self.class.repository == :parent
@@ -352,10 +452,22 @@ module ActiveTriples
352
452
  end
353
453
 
354
454
  ##
355
- # Takes a URI or String and aggressively tries to create a valid RDF URI.
356
- # Combines the input with base_uri if appropriate.
455
+ # Takes a URI or String and aggressively tries to convert it into
456
+ # an RDF term. If a String is given, first tries to interpret it
457
+ # as a valid URI, then tries to append it to base_uri. Finally,
458
+ # raises an error if no valid term can be built.
459
+ #
460
+ # The argument must be an RDF::Node, an object that responds to
461
+ # #to_uri, a String that represents a valid URI, or a String that
462
+ # appends to the Resource's base_uri to create a valid URI.
463
+ #
464
+ # @TODO: URI.scheme_list is naive and incomplete. Find a better
465
+ # way to check for an existing scheme.
357
466
  #
358
- # @TODO: URI.scheme_list is naive and incomplete. Find a better way to check for an existing scheme.
467
+ # @param uri_or_str [RDF::Resource, String]
468
+ #
469
+ # @return [RDF::Resource] A term
470
+ # @raise [RuntimeError] no valid RDF term could be built
359
471
  def get_uri(uri_or_str)
360
472
  return uri_or_str.to_uri if uri_or_str.respond_to? :to_uri
361
473
  return uri_or_str if uri_or_str.kind_of? RDF::Node