Class: ActiveTriples::Relation
- Inherits:
-
Object
- Object
- ActiveTriples::Relation
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/active_triples/relation.rb
Overview
A Relation represents the values of a specific property/predicate on an RDFSource. Each relation is a set (Array) of RDF::Terms that are objects in the of source’s triples of the form:
<{#parent}> <{#predicate}> [term] .
Relations express a set of binary relationships (on a predicate) between the parent node and a term.
When the term is a URI or Blank Node, it is represented in the results Array as an RDFSource with a graph selected as a subgraph of the parent’s. The triples in this subgraph are: (a) those whose subject is the term; (b) …
Defined Under Namespace
Classes: ValueError
Constant Summary collapse
- TYPE_PROPERTY =
{ predicate: RDF.type, cast: false }.freeze
Instance Attribute Summary collapse
-
#parent ⇒ RDFSource
The resource that is the domain of this relation.
- #reflections ⇒ Class readonly
- #rel_args ⇒ Hash
- #value_arguments ⇒ Array<Object>
Instance Method Summary collapse
- #&(array) ⇒ Array
- #+(array) ⇒ Array
-
#<<(values) ⇒ Relation
(also: #push)
Adds values to the result set.
-
#<=>(other) ⇒ Object
Mimics ‘Set#<=>`, returning
0when set membership is equivalent, andnil(as non-comparable) otherwise. -
#build(attributes = {}) ⇒ Object
Builds a node with the given attributes, adding it to the relation.
-
#clear ⇒ Relation
Empties the
Relation, deleting any associated triples fromparent. -
#delete(value) ⇒ ActiveTriples::Relation
Self.
-
#delete?(value) ⇒ Object?
A variation on
#delete. -
#each ⇒ Enumerator<Object>
Gives a result set for the
Relation. -
#empty? ⇒ Boolean
True if the results are empty.
-
#first_or_create(attributes = {}) ⇒ Object
deprecated
Deprecated.
for removal in 1.0.0. Use ‘first || build({})`, `build({}) if empty?` or similar logic.
-
#initialize(parent_source, value_arguments) ⇒ Relation
constructor
A new instance of Relation.
- #length ⇒ Integer
-
#predicate ⇒ RDF::Term?
Gives the predicate used by the Relation.
-
#property ⇒ Symbol, RDF::URI
Returns the property for the Relation.
-
#set(values) ⇒ Relation
Adds values to the relation.
-
#subtract(*values) ⇒ Relation
Self.
-
#swap(swap_out, swap_in) ⇒ Relation
Replaces the first argument with the second as a value within the relation.
- #|(array) ⇒ Array
Constructor Details
#initialize(parent_source, value_arguments) ⇒ Relation
Returns a new instance of Relation.
45 46 47 48 49 50 51 52 53 |
# File 'lib/active_triples/relation.rb', line 45 def initialize(parent_source, value_arguments) self.parent = parent_source @reflections = parent_source.reflections self.rel_args ||= {} self.rel_args = value_arguments.pop if value_arguments.is_a?(Array) && value_arguments.last.is_a?(Hash) self.value_arguments = value_arguments end |
Instance Attribute Details
#parent ⇒ RDFSource
Returns the resource that is the domain of this relation.
36 37 38 |
# File 'lib/active_triples/relation.rb', line 36 def parent @parent end |
#reflections ⇒ Class (readonly)
36 |
# File 'lib/active_triples/relation.rb', line 36 attr_accessor :parent, :value_arguments, :rel_args |
#rel_args ⇒ Hash
36 |
# File 'lib/active_triples/relation.rb', line 36 attr_accessor :parent, :value_arguments, :rel_args |
#value_arguments ⇒ Array<Object>
36 |
# File 'lib/active_triples/relation.rb', line 36 attr_accessor :parent, :value_arguments, :rel_args |
Instance Method Details
#&(array) ⇒ Array
simply passes to ‘Array#&` unless argument is a Relation
62 63 64 65 66 67 |
# File 'lib/active_triples/relation.rb', line 62 def &(array) return to_a & array unless array.is_a? Relation (objects.to_a & array.objects.to_a) .map { |object| convert_object(object) } end |
#+(array) ⇒ Array
simply passes to ‘Array#+` unless argument is a Relation
90 91 92 93 94 95 |
# File 'lib/active_triples/relation.rb', line 90 def +(array) return to_a + array unless array.is_a? Relation (objects.to_a + array.objects.to_a) .map { |object| convert_object(object) } end |
#<<(values) ⇒ Relation Also known as: push
Adds values to the result set
139 140 141 142 |
# File 'lib/active_triples/relation.rb', line 139 def <<(values) values = prepare_relation(values) if values.is_a?(Relation) self.set(objects.to_a | Array.wrap(values)) end |
#<=>(other) ⇒ Object
Mimics ‘Set#<=>`, returning 0 when set membership is equivalent, and nil (as non-comparable) otherwise. Unlike `Set#<=>`, uses `#==` for member comparisons.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/active_triples/relation.rb', line 105 def <=>(other) return nil unless other.respond_to?(:each) if empty? return 0 if other.each.first.nil? return nil end # We'll need to traverse `other` repeatedly, so we get a stable `Array` # representation. This avoids any repeated query cost if `other` is a # `Relation`. length = 0 other = other.to_a this = each loop do begin cur = this.next rescue StopIteration return other.length == length ? 0 : nil end length += 1 return nil if other.length < length || !other.include?(cur) end end |
#build(attributes = {}) ⇒ Object
Builds a node with the given attributes, adding it to the relation.
Nodes are built using the configured class_name for the relation. Attributes passed in the Hash argument are set on the new node through ‘RDFSource#attributes=`. If the attribute keys are not valid properties on the built node, we raise an error.
@todo: clarify class behavior; it is actually tied to type, in some cases.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/active_triples/relation.rb', line 190 def build(attributes={}) new_subject = attributes.fetch('id') { RDF::Node.new } make_node(new_subject).tap do |node| node.attributes = attributes.except('id') if parent.kind_of? List::ListResource parent.list << node elsif node.kind_of? RDF::List self.push node.rdf_subject else self.push node end end end |
#clear ⇒ Relation
Empties the Relation, deleting any associated triples from parent.
209 210 211 212 213 |
# File 'lib/active_triples/relation.rb', line 209 def clear parent.delete([rdf_subject, predicate, nil]) self end |
#delete(value) ⇒ ActiveTriples::Relation
this method behaves somewhat differently from ‘Array#delete`. It succeeds on deletion of non-existing values, always returning self unless an error is raised. There is no option to pass a block to evaluate if the value is not present. This is because access for value depends on query time. i.e. the Relation set does not have an underlying efficient data structure allowing a reliably cheap existence check.
symbols are treated as RDF::Nodes by default in ‘RDF::Mutable#delete`, but may also represent tokens in statements. This casts symbols to a literals, which gets us symmetric behavior between `#set(:sym)` and `#delete(:sym)`.
Returns self.
243 244 245 246 247 248 |
# File 'lib/active_triples/relation.rb', line 243 def delete(value) value = RDF::Literal(value) if value.is_a? Symbol parent.delete([rdf_subject, predicate, value]) self end |
#delete?(value) ⇒ Object?
A variation on #delete. This queries the relation for matching values before running the deletion, returning nil if it does not exist.
259 260 261 262 263 264 265 266 |
# File 'lib/active_triples/relation.rb', line 259 def delete?(value) value = RDF::Literal(value) if value.is_a? Symbol return nil if parent.query([rdf_subject, predicate, value]).nil? delete(value) value end |
#each ⇒ Enumerator<Object>
Gives a result set for the Relation.
By default, RDF::URI and RDF::Node results are cast to RDFSource. When cast? is false, RDF::Resource values are left in their raw form.
Literal results are cast as follows:
- Simple string literals are returned as `String`
- `rdf:langString` literals are always returned as raw `Literal` objects,
retaining their language .
- Typed literals are cast to their Ruby `#object` when their datatype
is associated with a `Literal` subclass.
309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/active_triples/relation.rb', line 309 def each return [].to_enum if predicate.nil? if block_given? objects do |object| converted_object = convert_object(object) yield converted_object unless converted_object.nil? end end to_enum end |
#empty? ⇒ Boolean
Returns true if the results are empty.
324 325 326 |
# File 'lib/active_triples/relation.rb', line 324 def empty? objects.empty? end |
#first_or_create(attributes = {}) ⇒ Object
for removal in 1.0.0. Use ‘first || build({})`, `build({}) if empty?` or similar logic.
Returns the first result, if present; else a newly built node.
335 336 337 338 |
# File 'lib/active_triples/relation.rb', line 335 def first_or_create(attributes={}) warn 'DEPRECATION: #first_or_create is deprecated for removal in 1.0.0.' first || build(attributes) end |
#length ⇒ Integer
342 343 344 |
# File 'lib/active_triples/relation.rb', line 342 def length objects.to_a.length end |
#predicate ⇒ RDF::Term?
Gives the predicate used by the Relation. Values of this object are those that match the pattern ‘<rdf_subject> <predicate> [value] .`
354 355 356 357 |
# File 'lib/active_triples/relation.rb', line 354 def predicate return property if property.is_a?(RDF::Term) property_config[:predicate] if is_property? end |
#property ⇒ Symbol, RDF::URI
Returns the property for the Relation. This may be a registered property key or an RDF::URI.
365 366 367 |
# File 'lib/active_triples/relation.rb', line 365 def property value_arguments.last end |
#set(values) ⇒ Relation
Adds values to the relation
384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/active_triples/relation.rb', line 384 def set(values) raise UndefinedPropertyError.new(property, reflections) if predicate.nil? values = prepare_relation(values) if values.is_a?(Relation) values = [values].compact unless values.kind_of?(Array) clear values.each { |val| set_value(val) } parent.persist! if parent.persistence_strategy.is_a? ParentStrategy self end |
#subtract(enum) ⇒ Relation #subtract(*values) ⇒ Relation
This casts symbols to a literals, which gets us symmetric behavior with ‘#set(:sym)`.
Returns self.
410 411 412 413 414 415 416 417 418 419 |
# File 'lib/active_triples/relation.rb', line 410 def subtract(*values) values = values.first if values.first.is_a? Enumerable statements = values.map do |value| value = RDF::Literal(value) if value.is_a? Symbol [rdf_subject, predicate, value] end parent.delete(*statements) self end |
#swap(swap_out, swap_in) ⇒ Relation
Replaces the first argument with the second as a value within the relation.
429 430 431 |
# File 'lib/active_triples/relation.rb', line 429 def swap(swap_out, swap_in) self.<<(swap_in) if delete?(swap_out) end |
#|(array) ⇒ Array
simply passes to ‘Array#|` unless argument is a Relation
76 77 78 79 80 81 |
# File 'lib/active_triples/relation.rb', line 76 def |(array) return to_a | array unless array.is_a? Relation (objects.to_a | array.objects.to_a) .map { |object| convert_object(object) } end |