Module: ActiveTriples::RDFSource
- Extended by:
- ActiveSupport::Concern
- Includes:
- ActiveModel::Conversion, ActiveModel::Serialization, ActiveModel::Serializers::JSON, ActiveModel::Validations, NestedAttributes, Persistable, Properties, RDF::Queryable, RDF::Value
- Included in:
- List::ListResource, Resource
- Defined in:
- lib/active_triples/rdf_source.rb
Overview
complete RDF::Value/RDF::Term/RDF::Resource interfaces
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.
An ‘RDFSource` is an RDF::Term—it can be used as a subject, predicate, object, or context in an RDF::Statement.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
-
#==(other) ⇒ Object
Compares self to other for RDF::Term equality.
-
#[](term_or_property) ⇒ Object
Returns an array of values belonging to the property requested.
-
#[]=(term_or_property, value) ⇒ Object
Adds or updates a property with supplied values.
-
#attributes ⇒ Hash<String, Array<Object>>
resource.attributes # => # “title”=>[“Comet in Moominland”, “Christmas in Moominvalley”], # “creator“=>.
- #attributes=(values) ⇒ Object
-
#base_uri ⇒ String?
The base URI the resource will use when setting its subject.
-
#dump(*args) ⇒ String
Returns a serialized string representation of self.
-
#fetch(*args) {|resource| ... } ⇒ ActiveTriples::RDFSource
Load data from the #rdf_subject URI.
- #get_relation(args) ⇒ Object
-
#get_values(*args) ⇒ ActiveTriples::Relation
Returns an array of values belonging to the property requested.
-
#graph_name ⇒ nil
Returns ‘nil` as the `graph_name`.
-
#humanize ⇒ String
A string identifier for the resource; ” if the resource is a node.
- #id ⇒ String
-
#initialize(*args, &block) ⇒ Object
Initialize an instance of this resource class.
- #mark_for_destruction ⇒ Object
- #marked_for_destruction? ⇒ Boolean
-
#new_record? ⇒ Boolean
Indicates if the record is ‘new’ (has not yet been persisted).
-
#node? ⇒ Boolean
True if the Term is a node.
-
#parent ⇒ Object
Delegate parent to the persistence strategy if possible.
- #parent=(parent) ⇒ Object
-
#rdf_label ⇒ Object
Looks for labels in various default fields, prioritizing configured label fields.
-
#rdf_subject ⇒ RDF::URI, RDF::Node
(also: #to_term)
Gives the representation of this RDFSource as an RDF::Term.
- #serializable_hash(options = nil) ⇒ Object
-
#set_subject!(uri_or_str) ⇒ Object
Set a new rdf_subject for the resource.
-
#set_value(*args) ⇒ ActiveTriples::Relation
Adds or updates a property by creating triples for each of the supplied values.
-
#to_uri ⇒ RDF::URI
The uri.
- #type ⇒ Object
- #type=(type) ⇒ Object
-
#uri? ⇒ Boolean
True if the Term is a uri.
Methods included from Persistable
#delete_statement, #destroy, #destroyed?, #each, #insert_statement, #persist!, #persisted?, #persistence_strategy, #reload, #set_persistence_strategy
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
#==(other) ⇒ Object
Compares self to other for RDF::Term equality.
Delegates the check to ‘other#==` passing it the term version of `self`.
123 124 125 |
# File 'lib/active_triples/rdf_source.rb', line 123 def ==(other) other == to_term end |
#[](term_or_property) ⇒ Object
Returns an array of values belonging to the property requested. Elements in the array may RdfResource objects or a valid datatype.
468 469 470 |
# File 'lib/active_triples/rdf_source.rb', line 468 def [](term_or_property) get_relation([term_or_property]) end |
#[]=(term_or_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.
481 482 483 |
# File 'lib/active_triples/rdf_source.rb', line 481 def []=(term_or_property, value) self[term_or_property].set(value) end |
#attributes ⇒ Hash<String, Array<Object>>
resource.attributes
# => {"id"=>"g47123700054720",
# "title"=>["Comet in Moominland", "Christmas in Moominvalley"],
# "creator"=>[#<Agent:0x2adbd76f1a5c(#<Agent:0x0055b7aede34b8>)>]}
resource << [resource, RDF::Vocab::DC.relation, 'Helsinki']
# => {"id"=>"g47123700054720",
# "title"=>["Comet in Moominland", "Christmas in Moominvalley"],
# "creator"=>[#<Agent:0x2adbd76f1a5c(#<Agent:0x0055b7aede34b8>)>],
# "http://purl.org/dc/terms/relation"=>["Helsinki"]}]}
@todo: should this, ‘#attributes=`, and `#serializable_hash` be moved out
into a dedicated `Serializer` object?
164 165 166 167 168 169 170 |
# File 'lib/active_triples/rdf_source.rb', line 164 def attributes attrs = {} attrs['id'] = 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
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/active_triples/rdf_source.rb', line 172 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 node? values.each do |key, value| if reflections.has_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.
296 297 298 |
# File 'lib/active_triples/rdf_source.rb', line 296 def base_uri self.class.base_uri 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
205 206 207 208 209 210 211 |
# File 'lib/active_triples/rdf_source.rb', line 205 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(*args) {|resource| ... } ⇒ ActiveTriples::RDFSource
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.
355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/active_triples/rdf_source.rb', line 355 def fetch(*args, &block) begin load(rdf_subject, *args) rescue => e if block_given? yield(self) else raise "#{self} is a blank node; Cannot fetch a resource without a URI" if node? raise e end end self end |
#get_relation(args) ⇒ Object
deprecate and remove? this is an alias to ‘#get_values`
488 489 490 491 492 493 494 |
# File 'lib/active_triples/rdf_source.rb', line 488 def get_relation(args) reload if (persistence_strategy.respond_to? :loaded?) && !persistence_strategy.loaded? @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(property) ⇒ ActiveTriples::Relation #get_values(uri, property) ⇒ ActiveTriples::Relation
should this raise an error when the property argument is not an RDF::Term or a registered property key?
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, which accesses properties directly on this RDFSource, is:
get_values(property)
459 460 461 |
# File 'lib/active_triples/rdf_source.rb', line 459 def get_values(*args) get_relation(args) end |
#graph_name ⇒ nil
Returns ‘nil` as the `graph_name`. This behavior mimics an `RDF::Graph` with no graph name, or one without named graph support.
@note: it’s possible to think of an ‘RDFSource` as “supporting named
graphs" in the sense that the `#rdf_subject` is an implied graph name.
For RDF.rb's purposes, however, it has a nil graph name: when
enumerating statements, we treat them as triples.
252 253 254 |
# File 'lib/active_triples/rdf_source.rb', line 252 def graph_name nil end |
#humanize ⇒ String
Returns A string identifier for the resource; ” if the resource is a node.
259 260 261 |
# File 'lib/active_triples/rdf_source.rb', line 259 def humanize node? ? '' : rdf_subject.to_s end |
#id ⇒ String
273 274 275 |
# File 'lib/active_triples/rdf_source.rb', line 273 def id node? ? rdf_subject.id : 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)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/active_triples/rdf_source.rb', line 92 def initialize(*args, &block) resource_uri = args.shift unless args.first.is_a?(Hash) @rdf_subject = get_uri(resource_uri) if resource_uri unless args.first.is_a?(Hash) || args.empty? set_persistence_strategy(ParentStrategy) persistence_strategy.parent = args.shift else set_persistence_strategy(RepositoryStrategy) end @graph = RDF::Graph.new(*args, &block) reload # Append type to graph if necessary. Array.wrap(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
535 536 537 |
# File 'lib/active_triples/rdf_source.rb', line 535 def mark_for_destruction @marked_for_destruction = true end |
#marked_for_destruction? ⇒ Boolean
539 540 541 |
# File 'lib/active_triples/rdf_source.rb', line 539 def marked_for_destruction? @marked_for_destruction end |
#new_record? ⇒ Boolean
Indicates if the record is ‘new’ (has not yet been persisted).
531 532 533 |
# File 'lib/active_triples/rdf_source.rb', line 531 def new_record? not persisted? end |
#node? ⇒ Boolean
Returns true if the Term is a node.
281 282 283 |
# File 'lib/active_triples/rdf_source.rb', line 281 def node? rdf_subject.node? end |
#parent ⇒ Object
establish a better pattern for this. ‘#parent` has been a public method in the past, but it’s probably time to deprecate it.
Delegate parent to the persistence strategy if possible
218 219 220 |
# File 'lib/active_triples/rdf_source.rb', line 218 def parent persistence_strategy.respond_to?(:parent) ? persistence_strategy.parent : nil end |
#parent=(parent) ⇒ Object
deprecate/remove
225 226 227 |
# File 'lib/active_triples/rdf_source.rb', line 225 def parent=(parent) persistence_strategy.respond_to?(:parent=) ? (persistence_strategy.parent = parent) : nil end |
#rdf_label ⇒ Object
Looks for labels in various default fields, prioritizing configured label fields.
314 315 316 317 318 319 320 321 322 |
# File 'lib/active_triples/rdf_source.rb', line 314 def rdf_label labels = Array.wrap(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
Gives the representation of this RDFSource as an RDF::Term
236 237 238 |
# File 'lib/active_triples/rdf_source.rb', line 236 def rdf_subject @rdf_subject ||= RDF::Node.new end |
#serializable_hash(options = nil) ⇒ Object
188 189 190 191 192 193 |
# File 'lib/active_triples/rdf_source.rb', line 188 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.
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/active_triples/rdf_source.rb', line 508 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(property, values) ⇒ ActiveTriples::Relation #set_value(subject, property, values) ⇒ ActiveTriples::Relation
This method will delete existing statements with the given subject and predicate from the graph
Adds or updates a property by creating triples for each of the supplied values.
The ‘property` argument may be either a symbol representing a registered property name, or an RDF::Term to use as the predicate.
The recommended pattern, which sets properties directly on this RDFSource, is: ‘set_value(property, values)`
426 427 428 429 430 431 432 433 |
# File 'lib/active_triples/rdf_source.rb', line 426 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 |
#to_uri ⇒ RDF::URI
Returns the uri.
265 266 267 |
# File 'lib/active_triples/rdf_source.rb', line 265 def to_uri rdf_subject if uri? end |
#type ⇒ Object
300 301 302 |
# File 'lib/active_triples/rdf_source.rb', line 300 def type self.get_values(:type) end |
#type=(type) ⇒ Object
304 305 306 307 |
# File 'lib/active_triples/rdf_source.rb', line 304 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 |
#uri? ⇒ Boolean
Returns true if the Term is a uri.
289 290 291 |
# File 'lib/active_triples/rdf_source.rb', line 289 def uri? rdf_subject.uri? end |