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.
349 350 351 |
# File 'lib/active_triples/rdf_source.rb', line 349 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.
326 327 328 |
# File 'lib/active_triples/rdf_source.rb', line 326 def []=(uri_or_term_property, value) self[uri_or_term_property].set(value) end |
#attributes ⇒ Object
135 136 137 138 139 140 141 |
# File 'lib/active_triples/rdf_source.rb', line 135 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
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/active_triples/rdf_source.rb', line 154 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.
212 213 214 |
# File 'lib/active_triples/rdf_source.rb', line 212 def base_uri self.class.base_uri end |
#destroy ⇒ Object Also known as: destroy!
392 393 394 395 396 397 |
# File 'lib/active_triples/rdf_source.rb', line 392 def destroy clear persist! if repository parent.destroy_child(self) if parent @destroyed = true end |
#destroy_child(child) ⇒ Object
408 409 410 411 412 |
# File 'lib/active_triples/rdf_source.rb', line 408 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.
404 405 406 |
# File 'lib/active_triples/rdf_source.rb', line 404 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
180 181 182 183 184 185 186 |
# File 'lib/active_triples/rdf_source.rb', line 180 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"
258 259 260 261 |
# File 'lib/active_triples/rdf_source.rb', line 258 def fetch load(rdf_subject) self end |
#fields ⇒ Array<Symbol>
Lists fields registered as properties on the object.
242 243 244 |
# File 'lib/active_triples/rdf_source.rb', line 242 def fields properties.keys.map(&:to_sym).reject{|x| x == :type} end |
#final_parent ⇒ Object
125 126 127 128 129 130 131 132 133 |
# File 'lib/active_triples/rdf_source.rb', line 125 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
354 355 356 357 358 359 |
# File 'lib/active_triples/rdf_source.rb', line 354 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)
341 342 343 |
# File 'lib/active_triples/rdf_source.rb', line 341 def get_values(*args) get_relation(args) end |
#id ⇒ Object
A string identifier for the resource
198 199 200 |
# File 'lib/active_triples/rdf_source.rb', line 198 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)
110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/active_triples/rdf_source.rb', line 110 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
422 423 424 |
# File 'lib/active_triples/rdf_source.rb', line 422 def mark_for_destruction @marked_for_destruction = true end |
#marked_for_destruction? ⇒ Boolean
426 427 428 |
# File 'lib/active_triples/rdf_source.rb', line 426 def marked_for_destruction? @marked_for_destruction end |
#new_record? ⇒ true, false
Indicates if the record is ‘new’ (has not yet been persisted).
418 419 420 |
# File 'lib/active_triples/rdf_source.rb', line 418 def new_record? not persisted? end |
#node? ⇒ Boolean
205 206 207 |
# File 'lib/active_triples/rdf_source.rb', line 205 def node? rdf_subject.node? end |
#persist!(opts = {}) ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/active_triples/rdf_source.rb', line 263 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.
282 283 284 285 286 |
# File 'lib/active_triples/rdf_source.rb', line 282 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.
228 229 230 231 232 233 234 235 236 |
# File 'lib/active_triples/rdf_source.rb', line 228 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.
191 192 193 |
# File 'lib/active_triples/rdf_source.rb', line 191 def rdf_subject @rdf_subject ||= RDF::Node.new end |
#reflections ⇒ Object
150 151 152 |
# File 'lib/active_triples/rdf_source.rb', line 150 def reflections self.class end |
#reload ⇒ true, false
Repopulates the graph from the repository or parent resource.
292 293 294 295 296 297 298 299 300 |
# File 'lib/active_triples/rdf_source.rb', line 292 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
143 144 145 146 147 148 |
# File 'lib/active_triples/rdf_source.rb', line 143 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.
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/active_triples/rdf_source.rb', line 373 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)
313 314 315 316 317 318 319 320 |
# File 'lib/active_triples/rdf_source.rb', line 313 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
216 217 218 |
# File 'lib/active_triples/rdf_source.rb', line 216 def type self.get_values(:type).to_a end |
#type=(type) ⇒ Object
220 221 222 223 |
# File 'lib/active_triples/rdf_source.rb', line 220 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.
95 96 97 |
# File 'lib/active_triples/rdf_source.rb', line 95 def writable? !frozen? end |