Class: RDFMapper::Model

Inherits:
Object
  • Object
show all
Includes:
Logger
Defined in:
lib/lib/model/base.rb,
lib/lib/model/output.rb,
lib/lib/model/property.rb,
lib/lib/model/attribute.rb,
lib/lib/model/association.rb

Overview

-

Defined Under Namespace

Classes: Attribute, Property

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logger

#debug, #fatal, #warn

Constructor Details

#initialize(attributes = {}) {|_self| ... } ⇒ Object

Creates a new instance of a model with specified attributes. Note that attributes include properties as well as associations. It also accepts URIs in addition to symbols:

class Company << RDFMapper::Model
  namespace 'http://myschema.com/#'
  has_many :people
end

class Person << RDFMapper::Model
  namespace 'http://myschema.com/#'
  attribute :name, :type => text
  belongs_to :company, :predicate => 'http://myschema.com/#employer'
end

The following two examples create identical models:

Person.new(:name => 'John')
Person.new('http://myschema.com/#name' => 'John')

And so do the following two examples:

@company = Company.new(:name => 'MyCo Inc.')

Person.new(:company => @company)
Person.new('http://myschema.com/#employer' => @company)

Parameters:

  • attributes (Hash) (defaults to: {})

    attributes of the new object

Yields:

  • (_self)

Yield Parameters:



435
436
437
438
439
440
441
442
443
444
445
446
# File 'lib/lib/model/base.rb', line 435

def initialize(attributes = {})
  @arbitrary = {}
  @attributes = {}
  @id = nil
  
  self.class.attributes.map do |name, att|
    @attributes[name] = att.value(self)
  end
  
  self.attributes = attributes
  yield self if block_given?
end

Class Method Details

.[](uri) ⇒ Object

Returns a model that subclassed RDFMapper::Model and has specified URI as its rdf:type

class Person < RDFMapper::Model
  type 'http://example.org/schema#Person'
end

class Company < RDFMapper::Model
  namespace 'http://example.org/schema#'
end

RDFMapper::Model['http://example.org/schema#Person']   #=> Person
RDFMapper::Model['http://example.org/schema#Company']  #=> Company
RDFMapper::Model['http://unknown-url.com/']            #=> nil

Parameters:

  • URI (String)
  • URI (RDF::URI)

Returns:

  • (Object)

    an RDFMapper model



165
166
167
168
169
170
# File 'lib/lib/model/base.rb', line 165

def [](uri)
  return nil if uri.nil?
  @@subclasses.select do |model|
    model.type.to_s == uri.to_s
  end.first
end

.adapter(instance) ⇒ Object .adapterObject

Sets or returns model’s connection adapter.

Overloads:

  • .adapter(instance) ⇒ Object

    Sets model’s connection adapter

    Parameters:

    • name (Symbol)

      adapter name (‘:rails`, `:rest` or `:sparql`)

    • options (Hash)

      options to pass on to the adapter constructor

  • .adapterObject

    Returns model’s connection adapter

Returns:

  • (Object)

    an instance of RDFMapper adapter



139
140
141
142
# File 'lib/lib/model/base.rb', line 139

def adapter(name = nil, options = {})
  return @adapter if name.nil?
  @adapter = RDFMapper::Adapters.register(name, self, options)
end

.all(*args) ⇒ Object

This is an alias for find(:all). You can pass in all the same arguments to this method as you can to find(:all).

See Also:



358
359
360
# File 'lib/lib/model/base.rb', line 358

def all(*args)
  find(:all, *args)
end

.associationsHash

Returns a hash of all associations with their names as keys and RDFMapper::Attribute instances as values.

Returns:

  • (Hash)


251
252
253
# File 'lib/lib/model/base.rb', line 251

def associations
  Hash[attributes.reject { |name, att| att.property? }]
end

.attribute(name, options = {}) ⇒ Object

Defines an attribute within a model.

Parameters:

  • name (Symbol)

    attribute name

  • options[:type] (Symbol)

    attribute type (:text, :uri, :integer, :float)

  • options[:predicate] (RDF::URI, String)

    RDF predicate

Returns:

  • (Object)

    instance of RDFMapper::Model::Attribute



264
265
266
267
268
269
270
271
272
273
274
# File 'lib/lib/model/base.rb', line 264

def attribute(name, options = {})
  attributes[name.to_sym] = Attribute.new(self, name.to_sym, options)
  class_eval <<-EOF
    def #{name}(*args, &block)
      get_attribute(:#{name}, *args, &block)
    end
    def #{name}=(value)
      set_attribute(:#{name}, value)
    end
  EOF
end

.attributesHash

Returns a hash of all attributes with their names as keys and RDFMapper::Attribute instances as values.

Returns:

  • (Hash)


231
232
233
# File 'lib/lib/model/base.rb', line 231

def attributes
  @attributes ||= {}
end

.belongs_to(name, options = {}) ⇒ Object

Specifies a one-to-one association with another class. The following methods for retrieval and query of the associated object will be added:

  • association(force_reload = false) – Returns the associated object. nil is returned if none is found.

  • association=(associate) – Assigns the associate object.

only if that name can’t be inferred from the association name

Parameters:

  • name (Symbol)

    name of the association

  • options[:class_name] (Symbol)

    class name of the association. Use it



52
53
54
# File 'lib/lib/model/association.rb', line 52

def belongs_to(name, options = {})
  attribute(name, options.merge(:association => :belongs_to))
end

.create(attributes) ⇒ Object?

Creates an object and saves it via the assigned adapter. The resulting object is returned whether the object was saved successfully to the database or not.

Parameters:

  • attributes (Hash)

    attributes of the new object

Returns:

  • (Object)

    instance of RDFMapper::Model

  • (nil)

    if save was unsuccessful



285
286
287
# File 'lib/lib/model/base.rb', line 285

def create(attributes)
  new(attributes).save(attributes[:id])
end

.find(*args) ⇒ Object

Find operates similarly to Rails’ ActiveRecord::Base.find function. It has the same four retrieval approaches:

  • Find by id – This can either be a specific id, a list of ids, or an array of ids ([5, 6, 10]).

  • Find first – This will return the first record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched, ‘nil` is returned. Use Model.find(:first, *args) or its shortcut Model.first(*args).

  • Find last - This will return the last record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched, ‘nil` is returned. Use Model.find(:last, *args) or its shortcut Model.last(*args).

  • Find all - This will return all the records matched by the options used. If no records are found, an empty array is returned. Use Model.find(:all, *args) or its shortcut Model.all(*args).



310
311
312
313
314
315
316
317
318
# File 'lib/lib/model/base.rb', line 310

def find(*args)
  options = args.last.is_a?(::Hash) ? args.pop : {}
  case args.first
    when :first   then find_every(options.merge(:limit => 1)).first
    when :last    then find_every(options).last
    when :all     then find_every(options)
    else find_from_ids(args, options)
  end
end

.find_or_create(atts = {}) ⇒ Object?

Either finds or creates an object with the specified ID.

Parameters:

  • attributes (Hash)

    attributes of the new object

Returns:

  • (Object)

    instance of RDFMapper::Model

  • (nil)

    if save was unsuccessful



327
328
329
330
# File 'lib/lib/model/base.rb', line 327

def find_or_create(atts = {})
  instance = atts[:id].nil? ? nil : find(atts[:id])
  instance.nil? ? create(atts) : instance
end

.first(*args) ⇒ Object

A convenience wrapper for find(:first, *args). You can pass in all the same arguments to this method as you can to find(:first).

See Also:



338
339
340
# File 'lib/lib/model/base.rb', line 338

def first(*args)
  find(:first, *args)
end

.has?(name, value = nil) ⇒ RDFMapper::Attribute?

Returns RDFMapper::Attribute that is assigned to the specified name. Accepts symbol, string, RDF::URI as a parameter. Value is optional and is used for associations.

class Person < RDFMapper::Model
  namespace 'http://example.org/schema#'
  attribute :name, :type => :text
  has_many :contacts, :predicate => 'http://example.org/schema#has'
  has_many :friends, :predicate => 'http://example.org/schema#has'
end

Person.has?(:name)                                          #=> #<RDFMapper::Model::Attribute>
Person.has?('http://example.org/schema#name')               #=> #<RDFMapper::Model::Attribute>
Person.has?('http://example.org/schema#unknown')            #=> nil

Person.has?('http://example.org/schema#has', Contact)       #=> #<RDFMapper::Model::Attribute>
Person.has?('http://example.org/schema#has', Contact.new)   #=> #<RDFMapper::Model::Attribute>
Person.has?(nil, Contact)                                   #=> #<RDFMapper::Model::Attribute>

Parameters:

  • name (Symbol, RDF::URI, String)
  • value (Object) (defaults to: nil)

Returns:

  • (RDFMapper::Attribute)
  • (nil)

    if attribute was not found



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/lib/model/base.rb', line 198

def has?(name, value = nil)
  if name.kind_of? String
    return has?(RDF::URI.new(name), value)
  end
  if name.kind_of? Symbol
    return attributes[name]
  end
  attributes.values.select do |att|
    att.matches?(name, value)
  end.first
end

.has_many(name, options = {}) ⇒ Object

Specifies a one-to-many association. The following methods for retrieval and query of collections of associated objects will be added:

  • collection(force_load = false) – Returns an array of all the associated objects. An empty array is returned if none are found.

  • collection<<(object, …) – Adds one or more objects to the collection by setting their foreign keys to the collection‘s primary key.

  • collection.delete(object, …) – Removes one or more objects from the collection by removing the association between objects.

  • collection=objects – Replaces the collections content by deleting and adding objects as appropriate.

  • collection.clear – Removes every object from the collection.

  • collection.empty? – Returns true if there are no associated objects.

  • collection.size – Returns the number of associated objects.

only if that name can’t be inferred from the association name

Parameters:

  • name (Symbol)

    name of the association

  • options[:class_name] (Symbol)

    class name of the association. Use it

Returns:

  • (Object)

    instance of RDFMapper::Attribute



34
35
36
# File 'lib/lib/model/association.rb', line 34

def has_many(name, options = {})
  attribute(name, options.merge(:association => :has_many))
end

.last(*args) ⇒ Object

A convenience wrapper for find(:last, *args). You can pass in all the same arguments to this method as you can to find(:last).

See Also:



348
349
350
# File 'lib/lib/model/base.rb', line 348

def last(*args)
  find(:last, *args)
end

.nameString

Returns model’s name without modules. Original class name is stored as ‘original_name’

module TestModule
  class Person < RDFMapper::Model; end
end

Person.name => 'Person'
Person.original_name => 'TestModule::Person'

Returns:

  • (String)


122
123
124
# File 'lib/lib/model/base.rb', line 122

def name
  original_name.split('::').last
end

.namespace(value) ⇒ RDF::Vocabulary .namespaceRDF::Vocabulary

Sets or returns model’s namespace. It is intended to operate as a shortcut: model and its attributes will calculate their RDF type and predicates automatically. The following two examples produce identical models:

class Person < RDFMapper::Model
  namespace 'http://example.org/schema#'
  attribute :name
  attribute :age
end

class Person < RDFMapper::Model 
  type 'http://example.org/schema#Person'
  attribute :name, :predicate => 'http://example.org/schema#name'
  attribute :age, :predicate => 'http://example.org/schema#age'
end

Person.type  #=> 'http://xmlns.com/foaf/0.1/Person'

Overloads:

  • .namespace(value) ⇒ RDF::Vocabulary

    Sets model’s namespace

    Parameters:

    • value (RDF::Vocabulary, RDF::URI, String)
  • .namespaceRDF::Vocabulary

    Returns model’s namespace

    Parameters:

    • (nil)

Returns:

  • (RDF::Vocabulary)

See Also:



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/lib/model/base.rb', line 47

def namespace(value = nil, options = {})
  @ns = options[:name] || 'myrdf'
  case value
    when NilClass
      @namespace
    when RDF::Vocabulary
      @namespace = value
    else
      @namespace = RDF::Vocabulary.new(value.to_s)
  end
end

.nsString

Returns the short name for model’s namespace. Defaults to ‘myrdf`

class Person < RDFMapper::Model
  namespace 'http://example.org/schema#', :name => 'my'
end

Person.ns        #=> 'example'
Person.to_xml    #=> '<my:Person></my:Person>'

Returns:

  • (String)


71
72
73
# File 'lib/lib/model/base.rb', line 71

def ns
  @ns.to_s || 'myrdf'
end

.original_nameObject

nodoc



15
# File 'lib/lib/model/base.rb', line 15

alias_method :original_name, :name

.propertiesHash

Returns a hash of all properties with their names as keys and RDFMapper::Attribute instances as values.

Returns:

  • (Hash)


241
242
243
# File 'lib/lib/model/base.rb', line 241

def properties
  Hash[attributes.select { |name, att| att.property? }]
end

.symbol(name, value = nil) ⇒ Symbol?

Returns the association name for the supplied predicate and / or value

Parameters:

  • name (Symbol, RDF::URI, String)
  • value (Object) (defaults to: nil)

Returns:

  • (Symbol)
  • (nil)

    if attribute was not found

See Also:



220
221
222
223
# File 'lib/lib/model/base.rb', line 220

def symbol(name, value = nil)
  att = has?(name, value)
  att.nil? ? nil : att.name
end

.type(value) ⇒ RDF::URI .typeRDF::URI

Sets or returns model’s RDF type

class Company < RDFMapper::Model
  type RDF::URI.new('http://example.org/schema#Company')
end

class Person < RDFMapper::Model
  type 'http://example.org/schema#Person'
end

Company.type  #=>  #<RDF::URI(http://example.org/schema#Company)>
Person.type   #=>  #<RDF::URI(http://example.org/schema#Person)>

Overloads:

  • .type(value) ⇒ RDF::URI

    Sets model’s RDF type

    Parameters:

    • value (RDF::URI, String)
  • .typeRDF::URI

    Parameters:

    • (nil)

Returns:

  • (RDF::URI)

See Also:



99
100
101
102
103
104
105
106
107
# File 'lib/lib/model/base.rb', line 99

def type(value = nil)
  unless value.nil?
    return @type = RDF::URI.new(value.to_s)
  end
  unless @type.nil?
    return @type
  end
  (nil == namespace) == true ? nil : namespace[name]
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?, equal?, new_record?

Compares instances based on their IDs.

Returns:

  • (Boolean)


462
463
464
465
# File 'lib/lib/model/base.rb', line 462

def ==(other)
  return false unless other.kind_of? self.class
  (other.nil? or other.id.nil?) ? false : (id == other.id)
end

#[](name) ⇒ Object

Returns the value of the attribute identified by ‘name` after it has been typecast (for example, “2004-12-12” is cast to a date object, like Date.new(2004, 12, 12)). (Alias for the private get_attribute method).

Parameters:

  • name (Symbol, String, RDF::URI)

    attribute name or predicate URI

Returns:

  • (Object)

    instance of a property or an association



479
480
481
482
483
484
# File 'lib/lib/model/base.rb', line 479

def [](name)
  unless name.kind_of? Symbol
    name = self.class.symbol(name)
  end
  name.nil? ? nil : get_attribute(name)
end

#[]=(name, value) ⇒ Object

Updates the attribute identified by ‘name` with the specified value. (Alias for the private set_attribute method).

Parameters:

  • name (Symbol, String, RDF::URI)

    attribute name or predicate URI

  • value (Object)

    new value of the attribute

Returns:

  • (Object)

    instance of a property or an association



496
497
498
499
500
501
# File 'lib/lib/model/base.rb', line 496

def []=(name, value)
  unless name.kind_of? Symbol
    name = self.class.symbol(name)
  end
  name.nil? ? nil : set_attribute(name, value)
end

#attributes(*args) ⇒ Hash

Returns a hash of all the attributes with their names as keys and the attributes’ values as values.

Returns:

  • (Hash)

    all attributes of an instance (name => value)



535
536
537
538
539
# File 'lib/lib/model/base.rb', line 535

def attributes(*args)
  Hash[@attributes.keys.map do |name|
    [ name, self[name] ]
  end].merge(@arbitrary).merge({ :id => id })
end

#attributes=(hash) ⇒ Hash

Allows you to set all the attributes at once by passing in a hash with keys matching attribute names or RDF predicates.

Parameters:

  • attributes (Hash)

    object’s new attributes

Returns:

  • (Hash)

    hash of all attributes (name => value)



548
549
550
551
# File 'lib/lib/model/base.rb', line 548

def attributes=(hash)
  return unless hash.kind_of? Hash
  hash.nil? ? nil : hash.each { |name, value| self[name] = value }
end

#foreign_keysHash

Returns a hash of all foreign keys (i.e. URIs) for belongs_to type of associations.

Returns:

  • (Hash)

    all foreign keys of an instance (name => uri)



521
522
523
524
525
526
527
# File 'lib/lib/model/base.rb', line 521

def foreign_keys
  Hash[self.class.associations.select do |name, assoc|
    assoc.belongs_to?
  end.map do |name, assoc|
    [ name, @attributes[name].keys ]
  end]
end

#id(*args) ⇒ String

Returns objects’s unique ID.

Returns:

  • (String)

    object’s ID (URI)



453
454
455
# File 'lib/lib/model/base.rb', line 453

def id(*args)
  @id.nil? ? nil : @id.dup
end

#inspectString

Developer-friendly representation of the instance.

Returns:

  • (String)


608
609
610
# File 'lib/lib/model/base.rb', line 608

def inspect #nodoc
  "#<%s:%s>" % [self.class, object_id]
end

#new?Boolean

Checks whether the model originated from or was saved to a data source (in other word, whether it has RDF ID).

Returns:

  • (Boolean)


559
560
561
# File 'lib/lib/model/base.rb', line 559

def new?
  id.nil?
end

#properties(*args) ⇒ Hash

Returns a hash of all the properties (i.e. attributes without associations).

Returns:

  • (Hash)

    all properties of an instance (name => value)



509
510
511
512
513
# File 'lib/lib/model/base.rb', line 509

def properties(*args)
  Hash[self.class.properties.keys.map do |name|
    [ name, self[name] ]
  end].merge(@arbitrary).merge({ :id => id })
end

#reloadObject

-


591
592
593
594
595
596
597
598
599
600
601
# File 'lib/lib/model/base.rb', line 591

def reload
  # Raise error if adapter is unspecified
  check_for_adapter

  if id.nil?
    raise RuntimeError, 'Reload failed. Model has no ID'
  end
  
  self.attributes = self.class.adapter.reload(self)
  self
end

#save(id = nil) ⇒ Object?

Saves the instance. If the model is new, a record gets created via the specified adapter (ID must be supplied in this case), otherwise the existing record gets updated.

Parameters:

  • id (RDF::URI, String) (defaults to: nil)

    object’s ID

Returns:

  • (Object)

    self

  • (nil)

    if save was unsuccessful



574
575
576
577
578
579
580
581
582
583
584
585
586
# File 'lib/lib/model/base.rb', line 574

def save(id = nil)
  # Raise error if adapter is unspecified
  check_for_adapter
        
  if new? and id.nil?
    raise RuntimeError, 'Save failed. ID must be specified'
  end
  if new?
    self.id = id
  end
  self.attributes = self.class.adapter.save(self)
  self
end

#to_statements(options = {}) ⇒ Object

options - class declaration only options - include associations



36
37
38
39
40
41
42
43
44
45
# File 'lib/lib/model/output.rb', line 36

def to_statements(options = {})
  if options[:full]
    atts = attribute_statements(options)
  elsif options[:short]
    return type_statement
  else
    atts = attribute_statements
  end
  type_statement + atts
end

#to_triples(options = {}) ⇒ Object

-


26
27
28
29
30
# File 'lib/lib/model/output.rb', line 26

def to_triples(options = {})
  to_statements(options).map do |statement|
    [ statement[:subject], statement[:predicate], statement[:object] ]
  end
end

#to_xml(options = {}) ⇒ String

RDF XML representaion of the instance.

Parameters:

  • options (Hash) (defaults to: {})
    TODO

Returns:

  • (String)


12
13
14
15
16
17
18
19
20
21
# File 'lib/lib/model/output.rb', line 12

def to_xml(options = {})
  RDF::Writer.for(:xml).buffer({ :declaration => false }) do |writer|
    if self.class.namespace
      writer.namespace!(self.class.namespace, self.class.ns)
    end
    to_triples.each do |triple|
      writer << triple
    end
  end
end