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 `0` when set membership is equivalent, and `nil` (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 from `parent`.
-
#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 |