rdf-mapper 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +188 -0
- data/UNLICENSE +25 -0
- data/VERSION +1 -0
- data/lib/lib/adapters/base.rb +83 -0
- data/lib/lib/adapters/rails.rb +307 -0
- data/lib/lib/adapters/rest.rb +45 -0
- data/lib/lib/adapters/sparql.rb +105 -0
- data/lib/lib/associations/base.rb +95 -0
- data/lib/lib/associations/belongs_to.rb +64 -0
- data/lib/lib/associations/has_and_belongs.rb +17 -0
- data/lib/lib/associations/has_many.rb +147 -0
- data/lib/lib/associations/has_one.rb +17 -0
- data/lib/lib/model/association.rb +59 -0
- data/lib/lib/model/attribute.rb +186 -0
- data/lib/lib/model/base.rb +623 -0
- data/lib/lib/model/output.rb +70 -0
- data/lib/lib/model/property.rb +78 -0
- data/lib/lib/scope/collection.rb +165 -0
- data/lib/lib/scope/condition.rb +132 -0
- data/lib/lib/scope/loader.rb +111 -0
- data/lib/lib/scope/model.rb +129 -0
- data/lib/lib/scope/query.rb +281 -0
- data/lib/lib/util/http.rb +66 -0
- data/lib/lib/util/logger.rb +68 -0
- data/lib/rdf-mapper.rb +15 -0
- metadata +141 -0
@@ -0,0 +1,623 @@
|
|
1
|
+
module RDFMapper
|
2
|
+
|
3
|
+
require 'lib/model/association'
|
4
|
+
require 'lib/model/output'
|
5
|
+
require 'lib/model/attribute'
|
6
|
+
require 'lib/model/property'
|
7
|
+
|
8
|
+
##
|
9
|
+
# [-]
|
10
|
+
##
|
11
|
+
class Model
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
alias_method :original_name, :name #nodoc
|
16
|
+
|
17
|
+
##
|
18
|
+
# Sets or returns model's namespace. It is intended to operate as a shortcut:
|
19
|
+
# model and its attributes will calculate their RDF type and predicates
|
20
|
+
# automatically. The following two examples produce identical models:
|
21
|
+
#
|
22
|
+
# class Person < RDFMapper::Model
|
23
|
+
# namespace 'http://example.org/schema#'
|
24
|
+
# attribute :name
|
25
|
+
# attribute :age
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# class Person < RDFMapper::Model
|
29
|
+
# type 'http://example.org/schema#Person'
|
30
|
+
# attribute :name, :predicate => 'http://example.org/schema#name'
|
31
|
+
# attribute :age, :predicate => 'http://example.org/schema#age'
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# Person.type #=> 'http://xmlns.com/foaf/0.1/Person'
|
35
|
+
#
|
36
|
+
# @overload namespace(value)
|
37
|
+
# Sets model's namespace
|
38
|
+
# @param [RDF::Vocabulary, RDF::URI, String] value
|
39
|
+
#
|
40
|
+
# @overload namespace
|
41
|
+
# Returns model's namespace
|
42
|
+
# @param [nil]
|
43
|
+
#
|
44
|
+
# @see type
|
45
|
+
# @return [RDF::Vocabulary]
|
46
|
+
##
|
47
|
+
def namespace(value = nil, options = {})
|
48
|
+
@ns = options[:name] || 'myrdf'
|
49
|
+
case value
|
50
|
+
when NilClass
|
51
|
+
@namespace
|
52
|
+
when RDF::Vocabulary
|
53
|
+
@namespace = value
|
54
|
+
else
|
55
|
+
@namespace = RDF::Vocabulary.new(value.to_s)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def ns
|
60
|
+
@ns || 'myrdf'
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Sets or returns model's RDF type
|
65
|
+
#
|
66
|
+
# class Company < RDFMapper::Model
|
67
|
+
# type RDF::URI.new('http://example.org/schema#Company')
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# class Person < RDFMapper::Model
|
71
|
+
# type 'http://example.org/schema#Person'
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# Company.type #=> #<RDF::URI(http://example.org/schema#Company)>
|
75
|
+
# Person.type #=> #<RDF::URI(http://example.org/schema#Person)>
|
76
|
+
#
|
77
|
+
# @overload type(value)
|
78
|
+
# Sets model's RDF type
|
79
|
+
# @param [RDF::URI, String] value
|
80
|
+
#
|
81
|
+
# @overload type
|
82
|
+
# @param [nil]
|
83
|
+
#
|
84
|
+
# @see namespace
|
85
|
+
# @return [RDF::URI]
|
86
|
+
##
|
87
|
+
def type(value = nil)
|
88
|
+
unless value.nil?
|
89
|
+
return @type = RDF::URI.new(value.to_s)
|
90
|
+
end
|
91
|
+
unless @type.nil?
|
92
|
+
return @type
|
93
|
+
end
|
94
|
+
(nil == namespace) == true ? nil : namespace[name]
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Returns model's name without modules. Original class name is stored
|
99
|
+
# as 'original_name'
|
100
|
+
#
|
101
|
+
# module TestModule
|
102
|
+
# class Person < RDFMapper::Model; end
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# Person.name => 'Person'
|
106
|
+
# Person.original_name => 'TestModule::Person'
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
##
|
110
|
+
def name
|
111
|
+
original_name.split('::').last
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Sets or returns model's connection adapter.
|
116
|
+
#
|
117
|
+
# @overload adapter(instance)
|
118
|
+
# Sets model's connection adapter
|
119
|
+
# @param [Symbol] name adapter name (`:rails`, `:rest` or `:sparql`)
|
120
|
+
# @param [Hash] options options to pass on to the adapter constructor
|
121
|
+
#
|
122
|
+
# @overload adapter
|
123
|
+
# Returns model's connection adapter
|
124
|
+
#
|
125
|
+
# @return [Object] an instance of RDFMapper adapter
|
126
|
+
##
|
127
|
+
def adapter(name = nil, options = {})
|
128
|
+
return @adapter if name.nil?
|
129
|
+
@adapter = RDFMapper::Adapters.register(name, self, options)
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Returns a model that subclassed {RDFMapper::Model} and has specified
|
134
|
+
# URI as its rdf:type
|
135
|
+
#
|
136
|
+
# class Person < RDFMapper::Model
|
137
|
+
# type 'http://example.org/schema#Person'
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# class Company < RDFMapper::Model
|
141
|
+
# namespace 'http://example.org/schema#'
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# RDFMapper::Model['http://example.org/schema#Person'] #=> Person
|
145
|
+
# RDFMapper::Model['http://example.org/schema#Company'] #=> Company
|
146
|
+
# RDFMapper::Model['http://unknown-url.com/'] #=> nil
|
147
|
+
#
|
148
|
+
# @param [String] URI
|
149
|
+
# @param [RDF::URI] URI
|
150
|
+
#
|
151
|
+
# @return [Object] an RDFMapper model
|
152
|
+
##
|
153
|
+
def [](uri)
|
154
|
+
return nil if uri.nil?
|
155
|
+
@@subclasses.select do |model|
|
156
|
+
model.type.to_s == uri.to_s
|
157
|
+
end.first
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Returns RDFMapper::Attribute that is assigned to the specified name.
|
162
|
+
# Accepts symbol, string, RDF::URI as a parameter. Value is optional
|
163
|
+
# and is used for associations.
|
164
|
+
#
|
165
|
+
# class Person < RDFMapper::Model
|
166
|
+
# namespace 'http://example.org/schema#'
|
167
|
+
# attribute :name, :type => :text
|
168
|
+
# has_many :contacts, :predicate => 'http://example.org/schema#has'
|
169
|
+
# has_many :friends, :predicate => 'http://example.org/schema#has'
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# Person.has?(:name) #=> #<RDFMapper::Model::Attribute>
|
173
|
+
# Person.has?('http://example.org/schema#name') #=> #<RDFMapper::Model::Attribute>
|
174
|
+
# Person.has?('http://example.org/schema#unknown') #=> nil
|
175
|
+
#
|
176
|
+
# Person.has?('http://example.org/schema#has', Contact) #=> #<RDFMapper::Model::Attribute>
|
177
|
+
# Person.has?('http://example.org/schema#has', Contact.new) #=> #<RDFMapper::Model::Attribute>
|
178
|
+
# Person.has?(nil, Contact) #=> #<RDFMapper::Model::Attribute>
|
179
|
+
#
|
180
|
+
# @param [Symbol, RDF::URI, String] name
|
181
|
+
# @param [Object] value
|
182
|
+
#
|
183
|
+
# @return [RDFMapper::Attribute]
|
184
|
+
# @return [nil] if attribute was not found
|
185
|
+
##
|
186
|
+
def has?(name, value = nil)
|
187
|
+
if name.kind_of? String
|
188
|
+
return has?(RDF::URI.new(name), value)
|
189
|
+
end
|
190
|
+
if name.kind_of? Symbol
|
191
|
+
return attributes[name]
|
192
|
+
end
|
193
|
+
attributes.values.select do |att|
|
194
|
+
att.matches?(name, value)
|
195
|
+
end.first
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Returns the association name for the supplied predicate and / or value
|
200
|
+
# @see has?
|
201
|
+
#
|
202
|
+
# @param [Symbol, RDF::URI, String] name
|
203
|
+
# @param [Object] value
|
204
|
+
#
|
205
|
+
# @return [Symbol]
|
206
|
+
# @return [nil] if attribute was not found
|
207
|
+
##
|
208
|
+
def symbol(name, value = nil)
|
209
|
+
att = has?(name, value)
|
210
|
+
att.nil? ? nil : att.name
|
211
|
+
end
|
212
|
+
|
213
|
+
##
|
214
|
+
# Returns a hash of all attributes with their names as keys and
|
215
|
+
# RDFMapper::Attribute instances as values.
|
216
|
+
#
|
217
|
+
# @return [Hash]
|
218
|
+
##
|
219
|
+
def attributes
|
220
|
+
@attributes ||= {}
|
221
|
+
end
|
222
|
+
|
223
|
+
##
|
224
|
+
# Returns a hash of all properties with their names as keys and
|
225
|
+
# RDFMapper::Attribute instances as values.
|
226
|
+
#
|
227
|
+
# @return [Hash]
|
228
|
+
##
|
229
|
+
def properties
|
230
|
+
Hash[attributes.select { |name, att| att.property? }]
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# Returns a hash of all associations with their names as keys and
|
235
|
+
# RDFMapper::Attribute instances as values.
|
236
|
+
#
|
237
|
+
# @return [Hash]
|
238
|
+
##
|
239
|
+
def associations
|
240
|
+
Hash[attributes.reject { |name, att| att.property? }]
|
241
|
+
end
|
242
|
+
|
243
|
+
##
|
244
|
+
# Defines an attribute within a model.
|
245
|
+
#
|
246
|
+
# @param [Symbol] name attribute name
|
247
|
+
# @param [Symbol] options[:type] attribute type (:text, :uri, :integer, :float)
|
248
|
+
# @param [RDF::URI, String] options[:predicate] RDF predicate
|
249
|
+
#
|
250
|
+
# @return [Object] instance of RDFMapper::Model::Attribute
|
251
|
+
##
|
252
|
+
def attribute(name, options = {})
|
253
|
+
attributes[name.to_sym] = Attribute.new(self, name.to_sym, options)
|
254
|
+
class_eval <<-EOF
|
255
|
+
def #{name}(*args, &block)
|
256
|
+
get_attribute(:#{name}, *args, &block)
|
257
|
+
end
|
258
|
+
def #{name}=(value)
|
259
|
+
set_attribute(:#{name}, value)
|
260
|
+
end
|
261
|
+
EOF
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
# Creates an object and saves it via the assigned adapter.
|
266
|
+
# The resulting object is returned whether the object was saved
|
267
|
+
# successfully to the database or not.
|
268
|
+
#
|
269
|
+
# @param [Hash] attributes attributes of the new object
|
270
|
+
# @param [RDF::URI, String] id object's ID
|
271
|
+
#
|
272
|
+
# @return [Object] instance of RDFMapper::Model
|
273
|
+
# @return [nil] if save was unsuccessful
|
274
|
+
##
|
275
|
+
def create(attributes, id)
|
276
|
+
new(attributes).save(id)
|
277
|
+
end
|
278
|
+
|
279
|
+
##
|
280
|
+
# Find operates similarly to Rails' ActiveRecord::Base.find function. It has
|
281
|
+
# the same four retrieval approaches:
|
282
|
+
#
|
283
|
+
# * Find by id -- This can either be a specific id, a list of ids, or
|
284
|
+
# an array of ids ([5, 6, 10]).
|
285
|
+
#
|
286
|
+
# * Find first -- This will return the first record matched by the
|
287
|
+
# options used. These options can either be specific conditions or
|
288
|
+
# merely an order. If no record can be matched, `nil` is returned.
|
289
|
+
# Use Model.find(:first, *args) or its shortcut Model.first(*args).
|
290
|
+
#
|
291
|
+
# * Find last - This will return the last record matched by the options
|
292
|
+
# used. These options can either be specific conditions or merely an
|
293
|
+
# order. If no record can be matched, `nil` is returned. Use
|
294
|
+
# Model.find(:last, *args) or its shortcut Model.last(*args).
|
295
|
+
#
|
296
|
+
# * Find all - This will return all the records matched by the options
|
297
|
+
# used. If no records are found, an empty array is returned. Use
|
298
|
+
# Model.find(:all, *args) or its shortcut Model.all(*args).
|
299
|
+
##
|
300
|
+
def find(*args)
|
301
|
+
options = args.last.is_a?(::Hash) ? args.pop : {}
|
302
|
+
case args.first
|
303
|
+
when :first then find_every(options.merge(:limit => 1)).first
|
304
|
+
when :last then find_every(options).last
|
305
|
+
when :all then find_every(options)
|
306
|
+
else find_from_ids(args, options)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
##
|
311
|
+
# Either finds or creates an object with the specified ID.
|
312
|
+
#
|
313
|
+
# @param [RDF::URI, String] id object's ID
|
314
|
+
# @param [Hash] attributes attributes of the new object
|
315
|
+
#
|
316
|
+
# @return [Object] instance of RDFMapper::Model
|
317
|
+
# @return [nil] if save was unsuccessful
|
318
|
+
##
|
319
|
+
def find_or_create(id, attributes = {})
|
320
|
+
instance = find(id)
|
321
|
+
instance.nil? ? create(id, attributes) : instance
|
322
|
+
end
|
323
|
+
|
324
|
+
##
|
325
|
+
# A convenience wrapper for find(:first, *args). You can pass in
|
326
|
+
# all the same arguments to this method as you can to find(:first).
|
327
|
+
#
|
328
|
+
# @see find
|
329
|
+
##
|
330
|
+
def first(*args)
|
331
|
+
find(:first, *args)
|
332
|
+
end
|
333
|
+
|
334
|
+
##
|
335
|
+
# A convenience wrapper for find(:last, *args). You can pass in
|
336
|
+
# all the same arguments to this method as you can to find(:last).
|
337
|
+
#
|
338
|
+
# @see find
|
339
|
+
##
|
340
|
+
def last(*args)
|
341
|
+
find(:last, *args)
|
342
|
+
end
|
343
|
+
|
344
|
+
##
|
345
|
+
# This is an alias for find(:all). You can pass in all the same
|
346
|
+
# arguments to this method as you can to find(:all).
|
347
|
+
#
|
348
|
+
# @see find
|
349
|
+
##
|
350
|
+
def all(*args)
|
351
|
+
find(:all, *args)
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
private
|
356
|
+
|
357
|
+
##
|
358
|
+
# Returns an Array of instances that match specified conditions.
|
359
|
+
# Note that they are not loaded until they are accessed (lazy loading)
|
360
|
+
##
|
361
|
+
def find_every(options) #nodoc
|
362
|
+
RDFMapper::Scope::Collection.new(self, options)
|
363
|
+
end
|
364
|
+
|
365
|
+
##
|
366
|
+
# Returns instances with specified IDs. Depending on the number
|
367
|
+
# of IDs it returns either an Array or a single instance (or nil
|
368
|
+
# if nothing was found)
|
369
|
+
##
|
370
|
+
def find_from_ids(ids, options) #nodoc
|
371
|
+
unless ids.kind_of?(Array)
|
372
|
+
ids = [ids]
|
373
|
+
end
|
374
|
+
options[:conditions] ||= { }
|
375
|
+
options[:conditions][:id] = ids
|
376
|
+
result = find_every(options)
|
377
|
+
case ids.size
|
378
|
+
when 0 then []
|
379
|
+
when 1 then result.first
|
380
|
+
else result
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
##
|
385
|
+
# Keeps track of all models that subclass RDFMapper::Model
|
386
|
+
##
|
387
|
+
def inherited(subclass) #nodoc
|
388
|
+
@@subclasses ||= []
|
389
|
+
@@subclasses << subclass
|
390
|
+
end
|
391
|
+
|
392
|
+
end
|
393
|
+
|
394
|
+
include RDFMapper::Logger
|
395
|
+
|
396
|
+
##
|
397
|
+
# Creates a new instance of a model with specified attributes.
|
398
|
+
# Note that attributes include properties as well as associations.
|
399
|
+
# It also accepts URIs in addition to symbols:
|
400
|
+
#
|
401
|
+
# class Company << RDFMapper::Model
|
402
|
+
# namespace 'http://myschema.com/#'
|
403
|
+
# has_many :people
|
404
|
+
# end
|
405
|
+
#
|
406
|
+
# class Person << RDFMapper::Model
|
407
|
+
# namespace 'http://myschema.com/#'
|
408
|
+
# attribute :name, :type => text
|
409
|
+
# belongs_to :company, :predicate => 'http://myschema.com/#employer'
|
410
|
+
# end
|
411
|
+
#
|
412
|
+
# The following two examples create identical models:
|
413
|
+
#
|
414
|
+
# Person.new(:name => 'John')
|
415
|
+
# Person.new('http://myschema.com/#name' => 'John')
|
416
|
+
#
|
417
|
+
# And so do the following two examples:
|
418
|
+
#
|
419
|
+
# @company = Company.new(:name => 'MyCo Inc.')
|
420
|
+
#
|
421
|
+
# Person.new(:company => @company)
|
422
|
+
# Person.new('http://myschema.com/#employer' => @company)
|
423
|
+
#
|
424
|
+
# @param [Hash] attributes attributes of the new object
|
425
|
+
# @return [Object] instance of RDFMapper::Model
|
426
|
+
##
|
427
|
+
def initialize(attributes = {})
|
428
|
+
@arbitrary = {}
|
429
|
+
@attributes = {}
|
430
|
+
@id = nil
|
431
|
+
|
432
|
+
self.class.attributes.map do |name, att|
|
433
|
+
@attributes[name] = att.value(self)
|
434
|
+
end
|
435
|
+
|
436
|
+
self.attributes = attributes
|
437
|
+
yield self if block_given?
|
438
|
+
end
|
439
|
+
|
440
|
+
##
|
441
|
+
# Returns objects's unique ID.
|
442
|
+
#
|
443
|
+
# @return [RDF::URI] object's ID
|
444
|
+
##
|
445
|
+
def id(*args)
|
446
|
+
@id.nil? ? nil : @id.dup
|
447
|
+
end
|
448
|
+
|
449
|
+
##
|
450
|
+
# Compares instances based on their IDs.
|
451
|
+
#
|
452
|
+
# @return [Boolean]
|
453
|
+
##
|
454
|
+
def ==(other)
|
455
|
+
(other.nil? or other.id.nil?) ? false : (id == other.id)
|
456
|
+
end
|
457
|
+
|
458
|
+
alias_method :eql?, :==
|
459
|
+
alias_method :equal?, :==
|
460
|
+
|
461
|
+
##
|
462
|
+
# Returns the value of the attribute identified by `name` after it
|
463
|
+
# has been typecast (for example, "2004-12-12" is cast to a date
|
464
|
+
# object, like Date.new(2004, 12, 12)). (Alias for the private
|
465
|
+
# get_attribute method).
|
466
|
+
#
|
467
|
+
# @param [Symbol, String, RDF::URI] name attribute name or predicate URI
|
468
|
+
# @return [Object] instance of a property or an association
|
469
|
+
##
|
470
|
+
def [](name)
|
471
|
+
unless name.kind_of? Symbol
|
472
|
+
name = self.class.symbol(name)
|
473
|
+
end
|
474
|
+
name.nil? ? nil : get_attribute(name)
|
475
|
+
end
|
476
|
+
|
477
|
+
##
|
478
|
+
# Updates the attribute identified by `name` with the specified
|
479
|
+
# value. (Alias for the private set_attribute method).
|
480
|
+
#
|
481
|
+
#
|
482
|
+
# @param [Symbol, String, RDF::URI] name attribute name or predicate URI
|
483
|
+
# @param [Object] value new value of the attribute
|
484
|
+
#
|
485
|
+
# @return [Object] instance of a property or an association
|
486
|
+
##
|
487
|
+
def []=(name, value)
|
488
|
+
unless name.kind_of? Symbol
|
489
|
+
name = self.class.symbol(name)
|
490
|
+
end
|
491
|
+
name.nil? ? nil : set_attribute(name, value)
|
492
|
+
end
|
493
|
+
|
494
|
+
##
|
495
|
+
# Returns a hash of all the attributes with their names as keys and
|
496
|
+
# the attributes' values as values.
|
497
|
+
#
|
498
|
+
# @return [Hash] all attributes of an instance (name => value)
|
499
|
+
##
|
500
|
+
def attributes(*args)
|
501
|
+
@attributes.merge(@arbitrary)
|
502
|
+
end
|
503
|
+
|
504
|
+
##
|
505
|
+
# Allows you to set all the attributes at once by passing in a hash
|
506
|
+
# with keys matching attribute names or RDF predicates.
|
507
|
+
#
|
508
|
+
# @param [Hash] attributes object's new attributes
|
509
|
+
# @return [Hash] hash of all attributes (name => value)
|
510
|
+
##
|
511
|
+
def attributes=(hash)
|
512
|
+
return unless hash.kind_of? Hash
|
513
|
+
hash.nil? ? nil : hash.each { |name, value| self[name] = value }
|
514
|
+
end
|
515
|
+
|
516
|
+
##
|
517
|
+
# Checks whether the model originated from or was saved to
|
518
|
+
# a data source (in other word, whether it has RDF ID).
|
519
|
+
#
|
520
|
+
# @return [Boolean]
|
521
|
+
##
|
522
|
+
def new?
|
523
|
+
id.nil?
|
524
|
+
end
|
525
|
+
|
526
|
+
alias_method :new_record?, :==
|
527
|
+
|
528
|
+
##
|
529
|
+
# Saves the instance. If the model is new, a record gets created
|
530
|
+
# via the specified adapter (ID must be supplied in this case),
|
531
|
+
# otherwise the existing record gets updated.
|
532
|
+
#
|
533
|
+
# @param [RDF::URI, String] id object's ID
|
534
|
+
# @return [Object] self
|
535
|
+
# @return [nil] if save was unsuccessful
|
536
|
+
##
|
537
|
+
def save(id = nil)
|
538
|
+
# Raise error if adapter is unspecified
|
539
|
+
check_for_adapter
|
540
|
+
|
541
|
+
if new? and id.nil?
|
542
|
+
raise RuntimeError, 'Save failed. ID must be specified'
|
543
|
+
end
|
544
|
+
if new?
|
545
|
+
self.id = id
|
546
|
+
end
|
547
|
+
self.attributes = self.class.adapter.save(self)
|
548
|
+
self
|
549
|
+
end
|
550
|
+
|
551
|
+
##
|
552
|
+
# [-]
|
553
|
+
##
|
554
|
+
def reload
|
555
|
+
# Raise error if adapter is unspecified
|
556
|
+
check_for_adapter
|
557
|
+
|
558
|
+
if id.nil?
|
559
|
+
raise RuntimeError, 'Reload failed. Model has no ID'
|
560
|
+
end
|
561
|
+
|
562
|
+
self.attributes = self.class.adapter.reload(self)
|
563
|
+
self
|
564
|
+
end
|
565
|
+
|
566
|
+
##
|
567
|
+
# Developer-friendly representation of the instance.
|
568
|
+
#
|
569
|
+
# @return [String]
|
570
|
+
##
|
571
|
+
def inspect #nodoc
|
572
|
+
"#<%s:%s>" % [self.class, object_id]
|
573
|
+
end
|
574
|
+
|
575
|
+
|
576
|
+
private
|
577
|
+
|
578
|
+
##
|
579
|
+
# Raises an error if adapter is undefined.
|
580
|
+
##
|
581
|
+
def check_for_adapter #nodoc
|
582
|
+
if self.class.adapter.nil?
|
583
|
+
raise RuntimeError, 'Save failed. Model adapter is undefined'
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
##
|
588
|
+
# Sets ID of this object (must be RDF::URI or a String).
|
589
|
+
##
|
590
|
+
def id=(value) #nodoc
|
591
|
+
@id = RDF::URI.new(value.to_s)
|
592
|
+
end
|
593
|
+
|
594
|
+
##
|
595
|
+
# Returns the value of an attribute identified by `name` after it
|
596
|
+
# has been typecast (for example, "2004-12-12" is cast to a date
|
597
|
+
# object, like Date.new(2004, 12, 12)).
|
598
|
+
##
|
599
|
+
def get_attribute(name, *args, &block) #nodoc
|
600
|
+
if @attributes.key?(name)
|
601
|
+
@attributes[name].object(*args, &block)
|
602
|
+
else
|
603
|
+
@arbitrary[name]
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
##
|
608
|
+
# Updates the attribute identified by `name` with the specified value.
|
609
|
+
##
|
610
|
+
def set_attribute(name, value) #nodoc
|
611
|
+
if name == :id
|
612
|
+
return nil
|
613
|
+
end
|
614
|
+
if @attributes.key?(name)
|
615
|
+
@attributes[name].replace(value)
|
616
|
+
else
|
617
|
+
@arbitrary[name] = value
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
end # Model
|
622
|
+
end # RDFMapper
|
623
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module RDFMapper
|
2
|
+
class Model
|
3
|
+
|
4
|
+
##
|
5
|
+
# RDF XML representaion of the instance.
|
6
|
+
#
|
7
|
+
# @todo. Not implemented
|
8
|
+
#
|
9
|
+
# @param [Hash] options [TODO]
|
10
|
+
# @return [String]
|
11
|
+
##
|
12
|
+
def to_xml(options = {})
|
13
|
+
RDF::Writer.for(:xml).buffer({ :declaration => false }) do |writer|
|
14
|
+
if self.class.namespace
|
15
|
+
writer.namespace!(self.class.namespace, self.class.ns)
|
16
|
+
end
|
17
|
+
to_triples.each do |triple|
|
18
|
+
writer << triple
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# [-]
|
25
|
+
##
|
26
|
+
def to_triples(options = {})
|
27
|
+
to_statements(options).map do |statement|
|
28
|
+
[ statement[:subject], statement[:predicate], statement[:object] ]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# options[:short] - class declaration only
|
34
|
+
# options[:full] - include associations
|
35
|
+
##
|
36
|
+
def to_statements(options = {})
|
37
|
+
if options[:full]
|
38
|
+
atts = attribute_statements(options)
|
39
|
+
elsif options[:short]
|
40
|
+
return type_statement
|
41
|
+
else
|
42
|
+
atts = attribute_statements
|
43
|
+
end
|
44
|
+
type_statement + atts
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
##
|
50
|
+
# [-]
|
51
|
+
##
|
52
|
+
def attribute_statements(options = {})
|
53
|
+
@attributes.map do |name, att|
|
54
|
+
att.to_statements(options)
|
55
|
+
end.flatten.compact
|
56
|
+
end
|
57
|
+
|
58
|
+
def associations_statements
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def type_statement
|
63
|
+
[{ :subject => id,
|
64
|
+
:predicate => RDF.type,
|
65
|
+
:object => self.class.type }]
|
66
|
+
end
|
67
|
+
|
68
|
+
end # Model
|
69
|
+
end # RDFMapper
|
70
|
+
|