Module: RDF::Queryable

Includes:
Enumerable
Included in:
Dataset, Enumerable::Enumerator, Graph, Enumerator, Transaction
Defined in:
lib/rdf/mixin/queryable.rb

Overview

An RDF query mixin.

Classes that include this module should implement a ‘#query_pattern` method that yields RDF statements. Classes may also implement an optimized `#query_execute` method that yields RDF statements.

See Also:

Defined Under Namespace

Classes: Enumerator

Instance Method Summary collapse

Instance Method Details

#enum_for(method = :each, *args) ⇒ Enumerator<RDF::Statement, RDF::Query::Pattern> Also known as: to_enum

Parameters:

  • method (Symbol, #to_sym) (defaults to: :each)

Returns:

See Also:

  • Object#enum_for


307
308
309
310
311
312
313
# File 'lib/rdf/mixin/queryable.rb', line 307

def enum_for(method = :each, *args)
  # Ensure that enumerators are, themselves, queryable
  this = self
  Queryable::Enumerator.new do |yielder|
    this.send(method, *args) {|*y| yielder << (y.length > 1 ? y : y.first)}
  end
end

#firstRDF::Statement #first(pattern) ⇒ RDF::Statement

Queries ‘self` for an RDF statement matching the given `pattern` and returns that statement if found.

Returns ‘nil` if no statements match `pattern`.

Overloads:

Returns:

Since:

  • 0.1.9



186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rdf/mixin/queryable.rb', line 186

def first(pattern = nil)
  if pattern
    query(pattern) do |statement|
      return statement
    end
  elsif respond_to?(:each_statement)
    each_statement do |statement|
      return statement
    end
  else
    return super()
  end
  nil
end

#first_literalRDF::Literal #first_literal(pattern) ⇒ RDF::Literal

Queries ‘self` for RDF statements matching the given `pattern` and returns the first found object literal.

Returns ‘nil` if no statements match `pattern` or if none of the found statements have a literal as their object term.

Overloads:

Returns:

Since:

  • 0.1.9



277
278
279
280
281
282
# File 'lib/rdf/mixin/queryable.rb', line 277

def first_literal(pattern = nil)
  __send__(*(pattern ? [:query, pattern] : [:each])) do |statement|
    return statement.object if statement.object.is_a?(RDF::Literal)
  end
  return nil
end

#first_objectRDF::Term #first_object(pattern) ⇒ RDF::Term

Queries ‘self` for an RDF statement matching the given `pattern` and returns the statement’s object term.

Returns ‘nil` if no statements match `pattern`.

Overloads:

Since:

  • 0.1.9



254
255
256
257
258
259
# File 'lib/rdf/mixin/queryable.rb', line 254

def first_object(pattern = nil)
  __send__(*(pattern ? [:query, pattern] : [:each])) do |statement|
    return statement.object
  end
  return nil
end

#first_predicateRDF::URI #first_predicate(pattern) ⇒ RDF::URI

Queries ‘self` for an RDF statement matching the given `pattern` and returns the statement’s predicate term.

Returns ‘nil` if no statements match `pattern`.

Overloads:

Since:

  • 0.1.9



234
235
236
237
238
239
# File 'lib/rdf/mixin/queryable.rb', line 234

def first_predicate(pattern = nil)
  __send__(*(pattern ? [:query, pattern] : [:each])) do |statement|
    return statement.predicate
  end
  return nil
end

#first_subjectRDF::Resource #first_subject(pattern) ⇒ RDF::Resource

Queries ‘self` for an RDF statement matching the given `pattern` and returns the statement’s subject term.

Returns ‘nil` if no statements match `pattern`.

Overloads:

Since:

  • 0.1.9



214
215
216
217
218
219
# File 'lib/rdf/mixin/queryable.rb', line 214

def first_subject(pattern = nil)
  __send__(*(pattern ? [:query, pattern] : [:each])) do |statement|
    return statement.subject
  end
  return nil
end

#first_valueObject #first_value(pattern) ⇒ Object

Queries ‘self` for RDF statements matching the given `pattern` and returns the value of the first found object literal.

Returns ‘nil` if no statements match `pattern` or if none of the found statements have a literal as their object term.

Overloads:

  • #first_valueObject

    Returns:

    • (Object)
  • #first_value(pattern) ⇒ Object

    Parameters:

    Returns:

    • (Object)

Since:

  • 0.1.9



298
299
300
# File 'lib/rdf/mixin/queryable.rb', line 298

def first_value(pattern = nil)
  (literal = first_literal(pattern)) ? literal.value : nil
end

#query(pattern, **options) {|statement| ... } ⇒ Enumerator<RDF::Statement>, ...

Note:

Since 2.0, this may return an Enumerable or an Enumerator in addition to Solutions

Queries ‘self` for RDF statements matching the given `pattern`.

This method delegates to the protected #query_pattern method for the actual lower-level query pattern matching implementation.

Examples:

Querying for statements having a given predicate

queryable.query([nil, RDF::Vocab::DOAP.developer, nil])
queryable.query({predicate: RDF::Vocab::DOAP.developer}) do |statement|
  puts statement.inspect
end

Querying for solutions from a BGP

query = RDF::Query.new {pattern [:s, :p, :o]}
queryable.query(query) do |solution|
  puts solution.inspect
end

Parameters:

  • pattern (RDF::Query, RDF::Statement, Array(RDF::Term), Hash)
  • options (Hash{Symbol => Object})

    ({}) Any other options passed to #query_pattern or #query_execute

Yields:

  • (statement)

    each matching statement

Yield Parameters:

Yield Returns:

  • (void)

    ignored

Returns:

Raises:

  • (TypeError)

See Also:

  • #query_pattern


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/rdf/mixin/queryable.rb', line 56

def query(pattern, **options, &block)
  raise TypeError, "#{self} is not readable" if respond_to?(:readable?) && !readable?

  case pattern
    # A basic graph pattern (BGP) query:
    when Query
      solutions = RDF::Query::Solutions.new
      block = lambda {|solution| solutions << solution} unless block_given?
      before_query(pattern) if respond_to?(:before_query)
      query_execute(pattern, **options, &block)
      after_query(pattern) if respond_to?(:after_query)
      # Returns the solutions, not an enumerator
      solutions
 
    # A simple triple/quad pattern query:
    else
      pattern = Query::Pattern.from(pattern)
      before_query(pattern) if respond_to?(:before_query)
      enum = case
        # Blank triple/quad patterns are equivalent to iterating over
        # every statement, so as a minor optimization we'll just do that
        # directly instead of bothering with `#query_pattern`:
        when pattern.blank?
          if block_given?
            each(&block)
          else
            to_a.extend(Queryable)
          end

        # Constant triple/quad patterns are equivalent to looking up a
        # particular statement, so as a minor optimization we'll just do
        # that directly instead of bothering with `#query_pattern`:
        when pattern.constant?
          statement = Statement.from(pattern)
          if include?(statement)
            if block_given?
              yield statement
            else
              [statement]
            end
          end

        # Otherwise, we delegate to `#query_pattern`:
        else # pattern.variable?
          query_pattern(pattern, **options, &block)
      end
      after_query(pattern) if respond_to?(:after_query)
      enum
  end
end