Class: Spira::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Callbacks, ActiveModel::Naming, Reflections, Resource
Includes:
ActiveModel::Conversion, ActiveModel::Dirty, ActiveModel::Serialization, RDF, RDF::Enumerable, RDF::Queryable, Persistence, Serialization, Types, Utils, Validations
Defined in:
lib/spira/base.rb

Overview

Spira::Base aims to perform similar to ActiveRecord::Base You should inherit your models from it.

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Resource

configure, has_many, property

Methods included from Reflections

reflect_on_association, reflections

Methods included from Serialization

#encode_with, #init_with

Methods included from Validations

#perform_validations, #save, #save!, #valid?

Methods included from Persistence

#count, #destroy, #destroy!, #destroyed?, #each, #new_record?, #persisted?, #save, #save!, #update_attributes

Methods included from Utils

#rename!

Constructor Details

#initialize(props = {}, options = {}) {|self| ... } ⇒ Base

Initialize a new Spira::Base instance of this resource class using a new blank node subject. Accepts a hash of arguments for initial attributes. To use a URI or existing blank node as a subject, use the .for method on the subclass instead.

Examples:

class Person < Spira::Base; end
bob = Person.for("bob")

Parameters:

  • props (Hash{Symbol => Any}) (defaults to: {})

    Default attributes for this instance

Yields:

  • (self)

    Executes a given block

Yield Parameters:

  • self (self)

    The newly created instance

See Also:



122
123
124
125
126
127
128
129
# File 'lib/spira/base.rb', line 122

def initialize(props = {}, options = {})
  @subject = props.delete(:_subject) || RDF::Node.new
  @attrs = {}

  reload props

  yield self if block_given?
end

Class Attribute Details

.propertiesObject (readonly)

Returns the value of attribute properties.



36
37
38
# File 'lib/spira/base.rb', line 36

def properties
  @properties
end

.reflectionsObject (readonly)

Returns the value of attribute reflections.



36
37
38
# File 'lib/spira/base.rb', line 36

def reflections
  @reflections
end

Instance Attribute Details

#subjectRDF::URI (readonly)

This instance’s URI.

Returns:



33
34
35
# File 'lib/spira/base.rb', line 33

def subject
  @subject
end

Class Method Details

.base_uriVoid

The base URI for this class. Attempts to create instances for non-URI objects will be appended to this base URI.

Returns:

  • (Void)


47
48
49
50
51
# File 'lib/spira/base.rb', line 47

def base_uri
  # should be redefined in children, if required
  # see also Spira::Resource.configure :base_uri option
  nil
end

.default_vocabularyVoid

The default vocabulary for this class. Setting a default vocabulary will allow properties to be defined without a :predicate option. Predicates will instead be created by appending the property name to the given string.

Returns:

  • (Void)


60
61
62
63
64
# File 'lib/spira/base.rb', line 60

def default_vocabulary
  # should be redefined in children, if required
  # see also Spira::Resource.configure :default_vocabulary option
  nil
end

.serialize(node, options = {}) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/spira/base.rb', line 66

def serialize(node, options = {})
  if node.respond_to?(:subject)
    node.subject
  elsif node.respond_to?(:blank?) && node.blank?
    nil
  else
    raise TypeError, "cannot serialize #{node.inspect} as a Spira resource"
  end
end

.typesObject



38
39
40
# File 'lib/spira/base.rb', line 38

def types
  Set.new
end

.unserialize(value, options = {}) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/spira/base.rb', line 76

def unserialize(value, options = {})
  if value.respond_to?(:blank?) && value.blank?
    nil
  else
    # Spira resources are instantiated as "promised"
    # to avoid instantiation loops in case of resource-to-resource relations.
    promise { instantiate_record(value) }
  end
end

Instance Method Details

#==(other) ⇒ Object

Compare this instance with another instance. The comparison is done on an RDF level, and will work across subclasses as long as the attributes are the same.



196
197
198
199
200
201
202
203
204
205
206
# File 'lib/spira/base.rb', line 196

def ==(other)
  # TODO: define behavior for equality on subclasses.
  # TODO: should we compare attributes here?
  if self.class == other.class
    subject == other.uri
  elsif other.is_a?(RDF::Enumerable)
    self.isomorphic_with?(other)
  else
    false
  end
end

#assign_attributes(attrs) ⇒ Object

Assign attributes to the resource without persisting it.



283
284
285
286
287
288
# File 'lib/spira/base.rb', line 283

def assign_attributes(attrs)
  attrs.each do |name, value|
    attribute_will_change!(name.to_s)
    send "#{name}=", value
  end
end

#attributesObject

Returns the attributes



132
133
134
# File 'lib/spira/base.rb', line 132

def attributes
  @attrs
end

#copy(new_subject) ⇒ Spira::Base

Returns a new instance of this class with the new subject instead of self.subject

Parameters:

  • new_subject (RDF::Resource)

Returns:



266
267
268
# File 'lib/spira/base.rb', line 266

def copy(new_subject)
  self.class.new(@attrs.merge(_subject: new_subject))
end

#copy!(new_subject) ⇒ Spira::Base, String

Returns a new instance of this class with the new subject instead of self.subject after saving the new copy to the repository.

Parameters:

  • new_subject (RDF::Resource)

Returns:



276
277
278
# File 'lib/spira/base.rb', line 276

def copy!(new_subject)
  copy(new_subject).save!
end

#freezeObject

Freeze the attributes hash such that associations are still accessible, even on destroyed records.



137
138
139
# File 'lib/spira/base.rb', line 137

def freeze
  @attrs.freeze; self
end

#frozen?Boolean

Returns true if the attributes hash has been frozen.

Returns:



142
143
144
# File 'lib/spira/base.rb', line 142

def frozen?
  @attrs.frozen?
end

#idObject



102
103
104
# File 'lib/spira/base.rb', line 102

def id
  new_record? ? nil : subject.path.split(/\//).last
end

#inspectObject

A developer-friendly view of this projection



186
187
188
# File 'lib/spira/base.rb', line 186

def inspect
  "<#{self.class}:#{self.object_id} @subject: #{@subject}>"
end

#node?true, false

Returns true if the subject associated with this instance is a blank node.

Returns:

  • (true, false)


247
248
249
# File 'lib/spira/base.rb', line 247

def node?
  subject.node?
end

#reload(props = {}) ⇒ Object

Assign all attributes from the given hash.



168
169
170
171
172
173
# File 'lib/spira/base.rb', line 168

def reload(props = {})
  reset_changes
  super
  assign_attributes(props)
  self
end

#respond_to?(*args) ⇒ Boolean

Returns true for :to_uri if this instance’s subject is a URI, and false if it is not. Returns true for :to_node if this instance’s subject is a Node, and false if it is not. Calls super otherwise.

Returns:



213
214
215
216
217
218
219
220
221
222
# File 'lib/spira/base.rb', line 213

def respond_to?(*args)
  case args[0]
  when :to_uri
    subject.respond_to?(:to_uri)
  when :to_node
    subject.node?
  else
    super(*args)
  end
end

#to_nodeRDF::Node

Returns the Node subject of this resource, if available. If this resource’s subject is a URI, raises a NoMethodError.

Returns:

Raises:

  • (NoMethodError)


257
258
259
# File 'lib/spira/base.rb', line 257

def to_node
  subject.node? ? subject : (raise NoMethodError, "No such method: :to_uri (this instance's subject is not a URI)")
end

#to_rdfRDF::Enumerable

Returns the RDF representation of this resource.

Returns:

  • (RDF::Enumerable)


179
180
181
# File 'lib/spira/base.rb', line 179

def to_rdf
  self
end

#to_uriRDF::URI

Returns the URI representation of this resource, if available. If this resource’s subject is a BNode, raises a NoMethodError.

Returns:

Raises:

  • (NoMethodError)


239
240
241
# File 'lib/spira/base.rb', line 239

def to_uri
  uri || (raise NoMethodError, "No such method: :to_uri (this instance's subject is not a URI)")
end

#typenil, RDF::URI

The RDF.type associated with this class.

This just takes a first type from “types” list, so make sure you know what you’re doing if you use it.

Returns:

  • (nil, RDF::URI)

    The RDF type associated with this instance’s class.



153
154
155
# File 'lib/spira/base.rb', line 153

def type
  self.class.type
end

#typesnil, RDF::URI

All RDF.type nodes associated with this class.

Returns:

  • (nil, RDF::URI)

    The RDF type associated with this instance’s class.



161
162
163
# File 'lib/spira/base.rb', line 161

def types
  self.class.types
end

#uriRDF::URI?

Returns the RDF::URI associated with this instance if this instance’s subject is an RDF::URI, and nil otherwise.

Returns:



229
230
231
# File 'lib/spira/base.rb', line 229

def uri
  subject.respond_to?(:to_uri) ? subject : nil
end