rdf-mapper 0.0.2 → 0.0.3
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 +18 -4
- data/VERSION +1 -1
- data/lib/lib/adapters/rails.rb +18 -10
- data/lib/lib/associations/base.rb +1 -1
- data/lib/lib/associations/belongs_to.rb +6 -0
- data/lib/lib/associations/has_many.rb +36 -14
- data/lib/lib/model/base.rb +51 -14
- data/lib/lib/model/property.rb +1 -1
- data/lib/lib/scope/collection.rb +19 -0
- data/lib/lib/scope/condition.rb +12 -3
- data/lib/lib/scope/loader.rb +22 -7
- data/lib/lib/scope/model.rb +13 -5
- data/lib/lib/scope/query.rb +19 -5
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -25,10 +25,10 @@ The latest version of RDFMapper can be found at
|
|
25
25
|
|
26
26
|
== Contribute
|
27
27
|
|
28
|
-
Please note that RDFMapper in under heavy development right now, it's not
|
29
|
-
production
|
30
|
-
welcome. Email us at team@42cities.com or submit
|
31
|
-
GitHub[http://github.com/42cities/rdf-mapper/issues]
|
28
|
+
Please note that RDFMapper in under *heavy* *development* right now, it's *not*
|
29
|
+
*yet* suitable for production environment. Any contribution (bug tickets,
|
30
|
+
code patches) is more than welcome. Email us at team@42cities.com or submit
|
31
|
+
a ticket on GitHub[http://github.com/42cities/rdf-mapper/issues].
|
32
32
|
|
33
33
|
|
34
34
|
= 5-minute crash course
|
@@ -186,3 +186,17 @@ That's pretty much all you need to know. Go try and let us know what you think!
|
|
186
186
|
|
187
187
|
RDFMapper is free and unencumbered public domain software. For more information,
|
188
188
|
see http://unlicense.org or the accompanying UNLICENSE file.
|
189
|
+
|
190
|
+
|
191
|
+
== Roadmap
|
192
|
+
|
193
|
+
Several important features are not yet implemented. Here's a rough list of what is still
|
194
|
+
to be done:
|
195
|
+
|
196
|
+
* Test coverage is extremely low (~10%)
|
197
|
+
* Documentation coverage is mediocre
|
198
|
+
* REST adapter is missing
|
199
|
+
* SPARQL adapter supports only simple `DESCRIBE` queries. At later stages it will most
|
200
|
+
likely use {sparql-client}[http://github.com/bendiken/sparql-client] library.
|
201
|
+
* JSON support is missing. Will use {rdf-json}[http://github.com/bendiken/rdf-json] library.
|
202
|
+
* `has_one` and `has_and_belongs_to_many` are missing
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/lib/lib/adapters/rails.rb
CHANGED
@@ -38,7 +38,7 @@ module RDFMapper
|
|
38
38
|
def save(instance)
|
39
39
|
if instance[:rails_id].nil?
|
40
40
|
obj = instance.class.find(instance.id.to_s).from(:rails)
|
41
|
-
instance[:rails_id] = obj
|
41
|
+
instance[:rails_id] = obj[:rails_id] unless obj.nil?
|
42
42
|
end
|
43
43
|
if instance[:rails_id].nil?
|
44
44
|
create(instance)
|
@@ -59,24 +59,27 @@ module RDFMapper
|
|
59
59
|
# [-]
|
60
60
|
##
|
61
61
|
def update(instance)
|
62
|
-
|
63
|
-
Query.new(query, @options).update
|
62
|
+
Query.new(default_query(instance), @options).update
|
64
63
|
end
|
65
64
|
|
66
65
|
##
|
67
66
|
# [-]
|
68
67
|
##
|
69
68
|
def create(instance)
|
70
|
-
|
71
|
-
Query.new(query, @options).create
|
69
|
+
Query.new(default_query(instance), @options).create
|
72
70
|
end
|
73
71
|
|
74
72
|
|
75
73
|
private
|
76
74
|
|
77
|
-
|
75
|
+
##
|
76
|
+
# [-]
|
77
|
+
##
|
78
|
+
def default_query(instance) #nodoc
|
79
|
+
conditions = {}.merge(instance.properties).merge(instance.foreign_keys)
|
80
|
+
RDFMapper::Scope::Query.new(instance.class, :conditions => conditions)
|
78
81
|
end
|
79
|
-
|
82
|
+
|
80
83
|
class Query
|
81
84
|
|
82
85
|
include RDFMapper::Logger
|
@@ -109,8 +112,8 @@ module RDFMapper
|
|
109
112
|
def find
|
110
113
|
@query.check(:rails_id)
|
111
114
|
#
|
112
|
-
debug 'Searching for %s with %s' % [@rails, @query.inspect]
|
113
|
-
debug 'Query: %s' % find_options.inspect
|
115
|
+
#debug 'Searching for %s with %s' % [@rails, @query.inspect]
|
116
|
+
#debug 'Query: %s' % find_options.inspect
|
114
117
|
#
|
115
118
|
@rails.find(:all, find_options).map do |record|
|
116
119
|
record_attributes(record)
|
@@ -138,7 +141,12 @@ module RDFMapper
|
|
138
141
|
def save_options
|
139
142
|
Hash[@query.to_a.map do |condition|
|
140
143
|
name = @replace[condition.name]
|
141
|
-
|
144
|
+
if condition.value.kind_of? RDFMapper::Model
|
145
|
+
value = condition.value[:rails_id]
|
146
|
+
else
|
147
|
+
value = condition.value
|
148
|
+
end
|
149
|
+
[name, value]
|
142
150
|
end.reject do |name, value|
|
143
151
|
name.nil? or value.nil?
|
144
152
|
end]
|
@@ -10,8 +10,12 @@ module RDFMapper
|
|
10
10
|
# objects as appropriate.
|
11
11
|
##
|
12
12
|
def replace(objects)
|
13
|
-
|
14
|
-
|
13
|
+
unless objects.kind_of? Array
|
14
|
+
objects = [objects]
|
15
|
+
end
|
16
|
+
|
17
|
+
new_objects = filter(objects)
|
18
|
+
return self if new_objects.empty?
|
15
19
|
|
16
20
|
new_objects.each do |child|
|
17
21
|
self << child
|
@@ -22,7 +26,7 @@ module RDFMapper
|
|
22
26
|
delete(child) unless new_objects.include?(child)
|
23
27
|
end
|
24
28
|
|
25
|
-
|
29
|
+
self
|
26
30
|
end
|
27
31
|
|
28
32
|
##
|
@@ -68,17 +72,18 @@ module RDFMapper
|
|
68
72
|
# Finds an associated object according to the same rules as
|
69
73
|
# RDFMapper::Model.find.
|
70
74
|
##
|
71
|
-
def find
|
72
|
-
|
75
|
+
def find(*args)
|
76
|
+
@association.find(*args).from(value)
|
73
77
|
end
|
74
78
|
|
75
79
|
##
|
76
|
-
# Returns
|
77
|
-
#
|
78
|
-
#
|
80
|
+
# Returns a new object of the collection type that has been
|
81
|
+
# instantiated with attributes and linked to this object,
|
82
|
+
# but not yet saved.
|
79
83
|
##
|
80
|
-
def build
|
81
|
-
|
84
|
+
def build(attributes)
|
85
|
+
obj = @association.new(attributes)
|
86
|
+
(self << obj).last
|
82
87
|
end
|
83
88
|
|
84
89
|
##
|
@@ -86,16 +91,24 @@ module RDFMapper
|
|
86
91
|
# instantiated with attributes, linked to this object through
|
87
92
|
# a foreign key, and that has already been saved.
|
88
93
|
##
|
89
|
-
def create
|
90
|
-
|
94
|
+
def create(attributes = {})
|
95
|
+
obj = @association.create(attributes.merge({ reverse => @instance }))
|
96
|
+
(self << obj).last
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Either finds or creates a new object in the collection.
|
101
|
+
##
|
102
|
+
def find_or_create(attributes = {})
|
103
|
+
obj = attributes[:id].nil? ? nil : find(attributes[:id])
|
104
|
+
obj.nil? ? create(attributes) : obj
|
91
105
|
end
|
92
106
|
|
93
107
|
##
|
94
108
|
# Returns true if a given object is present in the collection
|
95
109
|
##
|
96
110
|
def include?(object)
|
97
|
-
|
98
|
-
@value.include?(object)
|
111
|
+
value.include?(object)
|
99
112
|
end
|
100
113
|
|
101
114
|
##
|
@@ -105,6 +118,13 @@ module RDFMapper
|
|
105
118
|
value
|
106
119
|
end
|
107
120
|
|
121
|
+
##
|
122
|
+
# [-]
|
123
|
+
##
|
124
|
+
def kind_of?(cls)
|
125
|
+
cls == self.class || cls == Enumerable || cls == Array
|
126
|
+
end
|
127
|
+
|
108
128
|
|
109
129
|
private
|
110
130
|
|
@@ -124,10 +144,12 @@ module RDFMapper
|
|
124
144
|
if @instance.id.nil?
|
125
145
|
return []
|
126
146
|
end
|
147
|
+
@value = []
|
127
148
|
replace @association.find(:all, {
|
128
149
|
:conditions => { reverse => @instance },
|
129
150
|
:skip => [reverse]
|
130
151
|
})
|
152
|
+
@value
|
131
153
|
end
|
132
154
|
|
133
155
|
##
|
data/lib/lib/model/base.rb
CHANGED
@@ -56,8 +56,20 @@ module RDFMapper
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
##
|
60
|
+
# Returns the short name for model's namespace. Defaults to `myrdf`
|
61
|
+
#
|
62
|
+
# class Person < RDFMapper::Model
|
63
|
+
# namespace 'http://example.org/schema#', :name => 'my'
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# Person.ns #=> 'example'
|
67
|
+
# Person.to_xml #=> '<my:Person></my:Person>'
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
##
|
59
71
|
def ns
|
60
|
-
@ns || 'myrdf'
|
72
|
+
@ns.to_s || 'myrdf'
|
61
73
|
end
|
62
74
|
|
63
75
|
##
|
@@ -267,13 +279,11 @@ module RDFMapper
|
|
267
279
|
# successfully to the database or not.
|
268
280
|
#
|
269
281
|
# @param [Hash] attributes attributes of the new object
|
270
|
-
# @param [RDF::URI, String] id object's ID
|
271
|
-
#
|
272
282
|
# @return [Object] instance of RDFMapper::Model
|
273
283
|
# @return [nil] if save was unsuccessful
|
274
284
|
##
|
275
|
-
def create(attributes
|
276
|
-
new(attributes).save(id)
|
285
|
+
def create(attributes)
|
286
|
+
new(attributes).save(attributes[:id])
|
277
287
|
end
|
278
288
|
|
279
289
|
##
|
@@ -310,15 +320,13 @@ module RDFMapper
|
|
310
320
|
##
|
311
321
|
# Either finds or creates an object with the specified ID.
|
312
322
|
#
|
313
|
-
# @param [RDF::URI, String] id object's ID
|
314
323
|
# @param [Hash] attributes attributes of the new object
|
315
|
-
#
|
316
324
|
# @return [Object] instance of RDFMapper::Model
|
317
325
|
# @return [nil] if save was unsuccessful
|
318
326
|
##
|
319
|
-
def find_or_create(
|
320
|
-
instance = find(id)
|
321
|
-
instance.nil? ? create(
|
327
|
+
def find_or_create(atts = {})
|
328
|
+
instance = atts[:id].nil? ? nil : find(atts[:id])
|
329
|
+
instance.nil? ? create(atts) : instance
|
322
330
|
end
|
323
331
|
|
324
332
|
##
|
@@ -440,7 +448,7 @@ module RDFMapper
|
|
440
448
|
##
|
441
449
|
# Returns objects's unique ID.
|
442
450
|
#
|
443
|
-
# @return [
|
451
|
+
# @return [String] object's ID (URI)
|
444
452
|
##
|
445
453
|
def id(*args)
|
446
454
|
@id.nil? ? nil : @id.dup
|
@@ -452,6 +460,7 @@ module RDFMapper
|
|
452
460
|
# @return [Boolean]
|
453
461
|
##
|
454
462
|
def ==(other)
|
463
|
+
return false unless other.kind_of? self.class
|
455
464
|
(other.nil? or other.id.nil?) ? false : (id == other.id)
|
456
465
|
end
|
457
466
|
|
@@ -491,6 +500,32 @@ module RDFMapper
|
|
491
500
|
name.nil? ? nil : set_attribute(name, value)
|
492
501
|
end
|
493
502
|
|
503
|
+
##
|
504
|
+
# Returns a hash of all the properties (i.e. attributes without
|
505
|
+
# associations).
|
506
|
+
#
|
507
|
+
# @return [Hash] all properties of an instance (name => value)
|
508
|
+
##
|
509
|
+
def properties(*args)
|
510
|
+
Hash[self.class.properties.keys.map do |name|
|
511
|
+
[ name, self[name] ]
|
512
|
+
end].merge(@arbitrary).merge({ :id => id })
|
513
|
+
end
|
514
|
+
|
515
|
+
##
|
516
|
+
# Returns a hash of all foreign keys (i.e. URIs) for belongs_to
|
517
|
+
# type of associations.
|
518
|
+
#
|
519
|
+
# @return [Hash] all foreign keys of an instance (name => uri)
|
520
|
+
##
|
521
|
+
def foreign_keys
|
522
|
+
Hash[self.class.associations.select do |name, assoc|
|
523
|
+
assoc.belongs_to?
|
524
|
+
end.map do |name, assoc|
|
525
|
+
[ name, @attributes[name].keys ]
|
526
|
+
end]
|
527
|
+
end
|
528
|
+
|
494
529
|
##
|
495
530
|
# Returns a hash of all the attributes with their names as keys and
|
496
531
|
# the attributes' values as values.
|
@@ -498,7 +533,9 @@ module RDFMapper
|
|
498
533
|
# @return [Hash] all attributes of an instance (name => value)
|
499
534
|
##
|
500
535
|
def attributes(*args)
|
501
|
-
@attributes.
|
536
|
+
Hash[@attributes.keys.map do |name|
|
537
|
+
[ name, self[name] ]
|
538
|
+
end].merge(@arbitrary).merge({ :id => id })
|
502
539
|
end
|
503
540
|
|
504
541
|
##
|
@@ -537,7 +574,7 @@ module RDFMapper
|
|
537
574
|
def save(id = nil)
|
538
575
|
# Raise error if adapter is unspecified
|
539
576
|
check_for_adapter
|
540
|
-
|
577
|
+
|
541
578
|
if new? and id.nil?
|
542
579
|
raise RuntimeError, 'Save failed. ID must be specified'
|
543
580
|
end
|
@@ -588,7 +625,7 @@ module RDFMapper
|
|
588
625
|
# Sets ID of this object (must be RDF::URI or a String).
|
589
626
|
##
|
590
627
|
def id=(value) #nodoc
|
591
|
-
@id =
|
628
|
+
@id = value.to_s
|
592
629
|
end
|
593
630
|
|
594
631
|
##
|
data/lib/lib/model/property.rb
CHANGED
data/lib/lib/scope/collection.rb
CHANGED
@@ -127,6 +127,18 @@ module RDFMapper
|
|
127
127
|
items.include?(object)
|
128
128
|
end
|
129
129
|
|
130
|
+
##
|
131
|
+
# Invokes the block passing in successive elements from array,
|
132
|
+
# returning an array containing those elements for which the
|
133
|
+
# block returns a true value.
|
134
|
+
#
|
135
|
+
# @yield [Object]
|
136
|
+
# @return [Array]
|
137
|
+
##
|
138
|
+
def select(&block)
|
139
|
+
items.select { |x| block.call(x) }
|
140
|
+
end
|
141
|
+
|
130
142
|
##
|
131
143
|
# Converts collection into Array.
|
132
144
|
#
|
@@ -141,6 +153,13 @@ module RDFMapper
|
|
141
153
|
alias_method :slice, :[]
|
142
154
|
alias_method :include?, :exists?
|
143
155
|
|
156
|
+
##
|
157
|
+
# [-]
|
158
|
+
##
|
159
|
+
def kind_of?(cls)
|
160
|
+
cls == self.class || cls == Enumerable || cls == Array
|
161
|
+
end
|
162
|
+
|
144
163
|
##
|
145
164
|
# Developer-friendly representation of the instance
|
146
165
|
#
|
data/lib/lib/scope/condition.rb
CHANGED
@@ -18,10 +18,10 @@ module RDFMapper
|
|
18
18
|
if @att == :id
|
19
19
|
return @att
|
20
20
|
end
|
21
|
-
|
22
|
-
raise RuntimeError, 'Undefined attribute %s for %s' % [@att, @cls]
|
23
|
-
else
|
21
|
+
if att = @cls.has?(@att)
|
24
22
|
att.name
|
23
|
+
else
|
24
|
+
@att
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -34,6 +34,15 @@ module RDFMapper
|
|
34
34
|
|
35
35
|
alias_method :check, :value
|
36
36
|
|
37
|
+
##
|
38
|
+
# Checks whether specified object passes all conditions of the query.
|
39
|
+
#
|
40
|
+
# @param [RDFMapper::Model] object
|
41
|
+
##
|
42
|
+
def matches?(object)
|
43
|
+
object.send(name) == value
|
44
|
+
end
|
45
|
+
|
37
46
|
##
|
38
47
|
# [-]
|
39
48
|
##
|
data/lib/lib/scope/loader.rb
CHANGED
@@ -24,14 +24,29 @@ module RDFMapper
|
|
24
24
|
end
|
25
25
|
|
26
26
|
##
|
27
|
-
# Sets data adapter
|
27
|
+
# Sets data adapter or collection.
|
28
28
|
#
|
29
|
-
# @
|
30
|
-
#
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
# @overload type(adapter, options = {})
|
30
|
+
# Sets data adapter, this will override default model adapter
|
31
|
+
# @param [Symbol] adapter (:rails, :sparql, :rest)
|
32
|
+
# @param [Hash] options options to pass on to the adapter constructor
|
33
|
+
# @return [Object] adapter instance
|
34
|
+
#
|
35
|
+
# @overload type(collection)
|
36
|
+
# Sets collection of instances that should be queried.
|
37
|
+
# @param [Array] collection
|
38
|
+
##
|
39
|
+
def from(adapter_or_collection, options = {})
|
40
|
+
if adapter_or_collection.kind_of? Array
|
41
|
+
@loaded = true
|
42
|
+
adapter_or_collection.select do |instance|
|
43
|
+
@conditions.matches?(instance)
|
44
|
+
end.each do |instance|
|
45
|
+
@objects << instance.properties
|
46
|
+
end
|
47
|
+
return
|
48
|
+
end
|
49
|
+
@adapter = RDFMapper::Adapters.register(adapter_or_collection, @cls, options)
|
35
50
|
end
|
36
51
|
|
37
52
|
##
|
data/lib/lib/scope/model.rb
CHANGED
@@ -46,13 +46,21 @@ module RDFMapper
|
|
46
46
|
# In addition to the original method, preloads the model.
|
47
47
|
##
|
48
48
|
def [](name)
|
49
|
-
|
49
|
+
@arbitrary[name] || (@loaded ? super(name) : load[name])
|
50
50
|
end
|
51
51
|
|
52
52
|
##
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
53
|
+
# In addition to the original method, preloads the model.
|
54
|
+
#
|
55
|
+
# @return [Hash] all attributes of an instance (name => value)
|
56
|
+
##
|
57
|
+
def properties
|
58
|
+
check_for_nil_error
|
59
|
+
@loaded ? super : load.properties
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# In addition to the original method, preloads the model.
|
56
64
|
#
|
57
65
|
# @return [Hash] all attributes of an instance (name => value)
|
58
66
|
##
|
@@ -104,7 +112,7 @@ module RDFMapper
|
|
104
112
|
# In addition to the original method, preloads the model.
|
105
113
|
##
|
106
114
|
def get_attribute(name, *args)
|
107
|
-
@loaded ? super : load.send(name, *args)
|
115
|
+
@loaded ? super(name, *args) : load.send(name, *args)
|
108
116
|
end
|
109
117
|
|
110
118
|
##
|
data/lib/lib/scope/query.rb
CHANGED
@@ -74,6 +74,23 @@ module RDFMapper
|
|
74
74
|
nil
|
75
75
|
end
|
76
76
|
|
77
|
+
##
|
78
|
+
# Checks whether specified object passes all conditions of the query.
|
79
|
+
#
|
80
|
+
# @param [RDFMapper::Model] object
|
81
|
+
##
|
82
|
+
def matches?(object)
|
83
|
+
unless object.kind_of? RDFMapper::Model
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
unless object.class == @cls
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
to_a.reject do |condition|
|
90
|
+
condition.matches?(object)
|
91
|
+
end.empty?
|
92
|
+
end
|
93
|
+
|
77
94
|
##
|
78
95
|
# [-]
|
79
96
|
##
|
@@ -141,12 +158,9 @@ module RDFMapper
|
|
141
158
|
else
|
142
159
|
RDF::URI.new(self[:id].to_s)
|
143
160
|
end
|
144
|
-
|
145
|
-
:predicate => RDF.type,
|
146
|
-
:object => @cls.type
|
147
|
-
}] + to_a(:id).map do |condition|
|
161
|
+
to_a(:id).map do |condition|
|
148
162
|
condition.to_statements(target)
|
149
|
-
end.flatten.compact
|
163
|
+
end.flatten.compact + @cls.to_statements(:short => true)
|
150
164
|
end
|
151
165
|
|
152
166
|
##
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alex Serebryakov
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-28 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|