Module: ActiveTriples::RDFSource
- Extended by:
- ActiveSupport::Concern
- Includes:
- ActiveModel::Conversion, ActiveModel::Serialization, ActiveModel::Serializers::JSON, ActiveModel::Validations, NestedAttributes, Properties, Reflection, RDF::Countable, RDF::Durable, RDF::Enumerable, RDF::Mutable, RDF::Queryable, RDF::Value
- Included in:
- List::ListResource, Resource
- Defined in:
- lib/active_triples/rdf_source.rb
Overview
Defines a concern for managing RDF::Graph driven Resources as discrete, stateful graphs using ActiveModel-style objects.
An ‘RDFSource` models a resource (RDF::Resource) with a state that may change over time. The current state is represented by an RDF::Graph, accessible as #graph. The source is an RDF::Resource represented by #rdf_subject, which may be either an RDF::URI or an RDF::Node.
The graph of a source may contain contain arbitrary triples, including full representations of the state of other sources. The triples in the graph should be limited to statements that have bearing on the resource’s state.
Properties may be defined on inheriting classes to configure accessor methods for predicates.
Defined Under Namespace
Modules: ClassMethods
Instance Attribute Summary collapse
-
#parent ⇒ Object
Returns the value of attribute parent.
Class Method Summary collapse
Instance Method Summary collapse
-
#[](uri_or_term_property) ⇒ Object
Returns an array of values belonging to the property requested.
-
#[]=(uri_or_term_property, value) ⇒ Object
Adds or updates a property with supplied values.
- #attributes ⇒ Object
- #attributes=(values) ⇒ Object
-
#base_uri ⇒ String?
The base URI the resource will use when setting its subject.
- #destroy ⇒ Object (also: #destroy!)
- #destroy_child(child) ⇒ Object
-
#destroyed? ⇒ true, false
Indicates if the Resource has been destroyed.
-
#dump(*args) ⇒ String
Returns a serialized string representation of self.
-
#fetch ⇒ ActiveTriples::Entity
Load data from the #rdf_subject URI.
-
#fields ⇒ Array<Symbol>
Lists fields registered as properties on the object.
- #final_parent ⇒ Object
- #get_relation(args) ⇒ Object
-
#get_values(*args) ⇒ Object
Returns an array of values belonging to the property requested.
-
#id ⇒ Object
A string identifier for the resource.
-
#initialize(*args, &block) ⇒ Object
Initialize an instance of this resource class.
- #mark_for_destruction ⇒ Object
- #marked_for_destruction? ⇒ Boolean
-
#new_record? ⇒ true, false
Indicates if the record is ‘new’ (has not yet been persisted).
- #node? ⇒ Boolean
- #persist!(opts = {}) ⇒ Object
-
#persisted? ⇒ true, false
Indicates if the resource is persisted.
-
#rdf_label ⇒ Object
Looks for labels in various default fields, prioritizing configured label fields.
-
#rdf_subject ⇒ RDF::URI, RDF::Node
(also: #to_term)
A URI or Node which the resource’s properties are about.
- #reflections ⇒ Object
-
#reload ⇒ true, false
Repopulates the graph from the repository or parent resource.
- #serializable_hash(options = nil) ⇒ Object
-
#set_subject!(uri_or_str) ⇒ Object
Set a new rdf_subject for the resource.
-
#set_value(*args) ⇒ Object
Adds or updates a property with supplied values.
- #type ⇒ Object
- #type=(type) ⇒ Object
-
#writable? ⇒ true, false
Specifies whether the object is currently writable.
Methods included from Reflection
Instance Attribute Details
#parent ⇒ Object
Returns the value of attribute parent.
55 56 57 |
# File 'lib/active_triples/rdf_source.rb', line 55 def parent @parent end |
Class Method Details
.type_registry ⇒ Object
57 58 59 |
# File 'lib/active_triples/rdf_source.rb', line 57 def type_registry @@type_registry ||= {} end |
Instance Method Details
#[](uri_or_term_property) ⇒ Object
Returns an array of values belonging to the property requested. Elements in the array may RdfResource objects or a valid datatype.
342 343 344 |
# File 'lib/active_triples/rdf_source.rb', line 342 def [](uri_or_term_property) get_relation([uri_or_term_property]) end |
#[]=(uri_or_term_property, value) ⇒ Object
This method will delete existing statements with the correct subject and predicate from the graph
Adds or updates a property with supplied values.
319 320 321 |
# File 'lib/active_triples/rdf_source.rb', line 319 def []=(uri_or_term_property, value) self[uri_or_term_property].set(value) end |
#attributes ⇒ Object
128 129 130 131 132 133 134 |
# File 'lib/active_triples/rdf_source.rb', line 128 def attributes attrs = {} attrs['id'] = id if id fields.map { |f| attrs[f.to_s] = get_values(f) } unregistered_predicates.map { |uri| attrs[uri.to_s] = get_values(uri) } attrs end |
#attributes=(values) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/active_triples/rdf_source.rb', line 147 def attributes=(values) raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash values = values.with_indifferent_access id = values.delete(:id) set_subject!(id) if id && node? values.each do |key, value| if reflections.reflect_on_property(key) set_value(rdf_subject, key, value) elsif .keys.map { |k| "#{k}_attributes" }.include?(key) send("#{key}=".to_sym, value) else raise ArgumentError, "No association found for name `#{key}'. Has it been defined yet?" end end end |
#base_uri ⇒ String?
Returns the base URI the resource will use when setting its subject. ‘nil` if none is used.
205 206 207 |
# File 'lib/active_triples/rdf_source.rb', line 205 def base_uri self.class.base_uri end |
#destroy ⇒ Object Also known as: destroy!
385 386 387 388 389 390 |
# File 'lib/active_triples/rdf_source.rb', line 385 def destroy clear persist! if repository parent.destroy_child(self) if parent @destroyed = true end |
#destroy_child(child) ⇒ Object
401 402 403 404 405 |
# File 'lib/active_triples/rdf_source.rb', line 401 def destroy_child(child) statements.each do |statement| delete_statement(statement) if statement.subject == child.rdf_subject || statement.object == child.rdf_subject end end |
#destroyed? ⇒ true, false
Indicates if the Resource has been destroyed.
397 398 399 |
# File 'lib/active_triples/rdf_source.rb', line 397 def destroyed? @destroyed ||= false end |
#dump(*args) ⇒ String
Returns a serialized string representation of self. Extends the base implementation builds a JSON-LD context if the specified format is :jsonld and a context is provided by #jsonld_context
173 174 175 176 177 178 179 |
# File 'lib/active_triples/rdf_source.rb', line 173 def dump(*args) if args.first == :jsonld and respond_to?(:jsonld_context) args << {} unless args.last.is_a?(Hash) args.last[:context] ||= jsonld_context end super end |
#fetch ⇒ ActiveTriples::Entity
Load data from the #rdf_subject URI. Retrieved data will be parsed into the Resource’s graph from available RDF::Readers and available from property accessors if if predicates are registered.
osu = new('http://dbpedia.org/resource/Oregon_State_University')
osu.fetch
osu.rdf_label.first
# => "Oregon State University"
251 252 253 254 |
# File 'lib/active_triples/rdf_source.rb', line 251 def fetch load(rdf_subject) self end |
#fields ⇒ Array<Symbol>
Lists fields registered as properties on the object.
235 236 237 |
# File 'lib/active_triples/rdf_source.rb', line 235 def fields properties.keys.map(&:to_sym).reject{|x| x == :type} end |
#final_parent ⇒ Object
118 119 120 121 122 123 124 125 126 |
# File 'lib/active_triples/rdf_source.rb', line 118 def final_parent @final_parent ||= begin parent = self.parent while parent && parent.parent && parent.parent != parent parent = parent.parent end parent end end |
#get_relation(args) ⇒ Object
347 348 349 350 351 352 |
# File 'lib/active_triples/rdf_source.rb', line 347 def get_relation(args) @relation_cache ||= {} rel = Relation.new(self, args) @relation_cache["#{rel.send(:rdf_subject)}/#{rel.property}/#{rel.rel_args}"] ||= rel @relation_cache["#{rel.send(:rdf_subject)}/#{rel.property}/#{rel.rel_args}"] end |
#get_values(*args) ⇒ Object
Returns an array of values belonging to the property requested. Elements in the array may RdfResource objects or a valid datatype.
Handles two argument patterns. The recommended pattern is:
get_values(property)
For backwards compatibility, there is support for explicitly passing the rdf_subject to be used in th statement:
get_values(uri, property)
334 335 336 |
# File 'lib/active_triples/rdf_source.rb', line 334 def get_values(*args) get_relation(args) end |
#id ⇒ Object
A string identifier for the resource
191 192 193 |
# File 'lib/active_triples/rdf_source.rb', line 191 def id node? ? nil : rdf_subject.to_s end |
#initialize(*args, &block) ⇒ Object
move this logic out to a Builder?
Initialize an instance of this resource class. Defaults to a blank node subject. In addition to RDF::Graph parameters, you can pass in a URI and/or a parent to build a resource from a existing data.
You can pass in only a parent with:
new(nil, parent)
103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/active_triples/rdf_source.rb', line 103 def initialize(*args, &block) resource_uri = args.shift unless args.first.is_a?(Hash) self.parent = args.shift unless args.first.is_a?(Hash) @graph = RDF::Graph.new(*args, &block) set_subject!(resource_uri) if resource_uri reload # Append type to graph if necessary. Array(self.class.type).each do |type| unless self.get_values(:type).include?(type) self.get_values(:type) << type end end end |
#mark_for_destruction ⇒ Object
415 416 417 |
# File 'lib/active_triples/rdf_source.rb', line 415 def mark_for_destruction @marked_for_destruction = true end |
#marked_for_destruction? ⇒ Boolean
419 420 421 |
# File 'lib/active_triples/rdf_source.rb', line 419 def marked_for_destruction? @marked_for_destruction end |
#new_record? ⇒ true, false
Indicates if the record is ‘new’ (has not yet been persisted).
411 412 413 |
# File 'lib/active_triples/rdf_source.rb', line 411 def new_record? not persisted? end |
#node? ⇒ Boolean
198 199 200 |
# File 'lib/active_triples/rdf_source.rb', line 198 def node? rdf_subject.node? end |
#persist!(opts = {}) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/active_triples/rdf_source.rb', line 256 def persist!(opts={}) return if @persisting return false if opts[:validate] && !valid? @persisting = true run_callbacks :persist do raise "failed when trying to persist to non-existant repository or parent resource" unless repository erase_old_resource repository << self @persisted = true end @persisting = false true end |
#persisted? ⇒ true, false
Indicates if the resource is persisted.
275 276 277 278 279 |
# File 'lib/active_triples/rdf_source.rb', line 275 def persisted? @persisted ||= false return (@persisted and parent.persisted?) if parent @persisted end |
#rdf_label ⇒ Object
Looks for labels in various default fields, prioritizing configured label fields.
221 222 223 224 225 226 227 228 229 |
# File 'lib/active_triples/rdf_source.rb', line 221 def rdf_label labels = Array(self.class.rdf_label) labels += default_labels labels.each do |label| values = get_values(label) return values unless values.empty? end node? ? [] : [rdf_subject.to_s] end |
#rdf_subject ⇒ RDF::URI, RDF::Node Also known as: to_term
Returns a URI or Node which the resource’s properties are about.
184 185 186 |
# File 'lib/active_triples/rdf_source.rb', line 184 def rdf_subject @rdf_subject ||= RDF::Node.new end |
#reflections ⇒ Object
143 144 145 |
# File 'lib/active_triples/rdf_source.rb', line 143 def reflections self.class end |
#reload ⇒ true, false
Repopulates the graph from the repository or parent resource.
285 286 287 288 289 290 291 292 293 |
# File 'lib/active_triples/rdf_source.rb', line 285 def reload @relation_cache ||= {} return false unless repository self << repository.query(subject: rdf_subject) unless empty? @persisted = true end true end |
#serializable_hash(options = nil) ⇒ Object
136 137 138 139 140 141 |
# File 'lib/active_triples/rdf_source.rb', line 136 def serializable_hash( = nil) attrs = (fields.map { |f| f.to_s }) << 'id' hash = super(:only => attrs) unregistered_predicates.map { |uri| hash[uri.to_s] = get_values(uri) } hash end |
#set_subject!(uri_or_str) ⇒ Object
Set a new rdf_subject for the resource.
This raises an error if the current subject is not a blank node, and returns false if it can’t figure out how to make a URI from the param. Otherwise it creates a URI for the resource and rebuilds the graph with the updated URI.
Will try to build a uri as an extension of the class’s base_uri if appropriate.
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/active_triples/rdf_source.rb', line 366 def set_subject!(uri_or_str) raise "Refusing update URI when one is already assigned!" unless node? or rdf_subject == RDF::URI(nil) # Refusing set uri to an empty string. return false if uri_or_str.nil? or (uri_or_str.to_s.empty? and not uri_or_str.kind_of? RDF::URI) # raise "Refusing update URI! This object is persisted to a datastream." if persisted? old_subject = rdf_subject @rdf_subject = get_uri(uri_or_str) each_statement do |statement| if statement.subject == old_subject delete(statement) self << RDF::Statement.new(rdf_subject, statement.predicate, statement.object) elsif statement.object == old_subject delete(statement) self << RDF::Statement.new(statement.subject, statement.predicate, rdf_subject) end end end |
#set_value(*args) ⇒ Object
This method will delete existing statements with the correct subject and predicate from the graph
Adds or updates a property with supplied values.
Handles two argument patterns. The recommended pattern is:
set_value(property, values)
For backwards compatibility, there is support for explicitly passing the rdf_subject to be used in the statement:
set_value(uri, property, values)
306 307 308 309 310 311 312 313 |
# File 'lib/active_triples/rdf_source.rb', line 306 def set_value(*args) # Add support for legacy 3-parameter syntax if args.length > 3 || args.length < 2 raise ArgumentError, "wrong number of arguments (#{args.length} for 2-3)" end values = args.pop get_relation(args).set(values) end |
#type ⇒ Object
209 210 211 |
# File 'lib/active_triples/rdf_source.rb', line 209 def type self.get_values(:type).to_a end |
#type=(type) ⇒ Object
213 214 215 216 |
# File 'lib/active_triples/rdf_source.rb', line 213 def type=(type) raise "Type must be an RDF::URI" unless type.kind_of? RDF::URI self.update(RDF::Statement.new(rdf_subject, RDF.type, type)) end |
#writable? ⇒ true, false
Specifies whether the object is currently writable.
88 89 90 |
# File 'lib/active_triples/rdf_source.rb', line 88 def writable? !frozen? end |