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) ⇒ void
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`.
124 125 126 |
# File 'lib/active_triples/rdf_source.rb', line 124 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.
469 470 471 |
# File 'lib/active_triples/rdf_source.rb', line 469 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.
482 483 484 |
# File 'lib/active_triples/rdf_source.rb', line 482 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?
165 166 167 168 169 170 171 |
# File 'lib/active_triples/rdf_source.rb', line 165 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
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/active_triples/rdf_source.rb', line 173 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.
297 298 299 |
# File 'lib/active_triples/rdf_source.rb', line 297 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
206 207 208 209 210 211 212 |
# File 'lib/active_triples/rdf_source.rb', line 206 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.
356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/active_triples/rdf_source.rb', line 356 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`
489 490 491 492 493 494 495 |
# File 'lib/active_triples/rdf_source.rb', line 489 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)
460 461 462 |
# File 'lib/active_triples/rdf_source.rb', line 460 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.
253 254 255 |
# File 'lib/active_triples/rdf_source.rb', line 253 def graph_name nil end |
#humanize ⇒ String
Returns A string identifier for the resource; ” if the resource is a node.
260 261 262 |
# File 'lib/active_triples/rdf_source.rb', line 260 def humanize node? ? '' : rdf_subject.to_s end |
#id ⇒ String
274 275 276 |
# File 'lib/active_triples/rdf_source.rb', line 274 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 112 |
# 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
532 533 534 |
# File 'lib/active_triples/rdf_source.rb', line 532 def mark_for_destruction @marked_for_destruction = true end |
#marked_for_destruction? ⇒ Boolean
536 537 538 |
# File 'lib/active_triples/rdf_source.rb', line 536 def marked_for_destruction? @marked_for_destruction end |
#new_record? ⇒ Boolean
Indicates if the record is ‘new’ (has not yet been persisted).
528 529 530 |
# File 'lib/active_triples/rdf_source.rb', line 528 def new_record? not persisted? end |
#node? ⇒ Boolean
Returns true if the Term is a node.
282 283 284 |
# File 'lib/active_triples/rdf_source.rb', line 282 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
219 220 221 |
# File 'lib/active_triples/rdf_source.rb', line 219 def parent persistence_strategy.respond_to?(:parent) ? persistence_strategy.parent : nil end |
#parent=(parent) ⇒ Object
deprecate/remove
226 227 228 |
# File 'lib/active_triples/rdf_source.rb', line 226 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.
315 316 317 318 319 320 321 322 323 |
# File 'lib/active_triples/rdf_source.rb', line 315 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
237 238 239 |
# File 'lib/active_triples/rdf_source.rb', line 237 def rdf_subject @rdf_subject ||= RDF::Node.new end |
#serializable_hash(options = nil) ⇒ Object
189 190 191 192 193 194 |
# File 'lib/active_triples/rdf_source.rb', line 189 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) ⇒ void
This method returns an undefined value.
Set a new rdf_subject for the resource.
Will try to build a uri as an extension of the class’s base_uri if appropriate.
510 511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/active_triples/rdf_source.rb', line 510 def set_subject!(uri_or_str) raise "Refusing update URI when one is already assigned!" unless node? || rdf_subject == RDF::URI(nil) return false if uri_or_str.nil? || (uri_or_str.to_s.empty? && !uri_or_str.kind_of?(RDF::URI)) new_subject = get_uri(uri_or_str) rewrite_statement_uris(rdf_subject, new_subject) @rdf_subject = new_subject 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)`
427 428 429 430 431 432 433 434 |
# File 'lib/active_triples/rdf_source.rb', line 427 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.
266 267 268 |
# File 'lib/active_triples/rdf_source.rb', line 266 def to_uri rdf_subject if uri? end |
#type ⇒ Object
301 302 303 |
# File 'lib/active_triples/rdf_source.rb', line 301 def type self.get_values(:type) end |
#type=(type) ⇒ Object
305 306 307 308 |
# File 'lib/active_triples/rdf_source.rb', line 305 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.
290 291 292 |
# File 'lib/active_triples/rdf_source.rb', line 290 def uri? rdf_subject.uri? end |