active-triples 0.1.0 → 0.1.1

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 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