rdf-mapper 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 yet
29
- production safe. Any contribution (bug tickets, code patches) is more than
30
- welcome. Email us at team@42cities.com or submit a ticket on
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.2
1
+ 0.0.3
@@ -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.rails_id unless obj.nil?
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
- query = RDFMapper::Scope::Query.new(instance.class, :conditions => instance.attributes)
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
- query = RDFMapper::Scope::Query.new(instance.class, :conditions => instance.attributes)
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
- def check_for_rails_id(instance)
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
- [name, validate(condition.value)]
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]
@@ -20,7 +20,7 @@ module RDFMapper
20
20
  end
21
21
 
22
22
  ##
23
- # [-]
23
+ # Association should override this method
24
24
  ##
25
25
  def replace(value)
26
26
  raise NotImplementedError, 'Expected association to override `replace`'
@@ -43,6 +43,12 @@ module RDFMapper
43
43
  end
44
44
  end
45
45
 
46
+ ##
47
+ # Returns the 'foreign key' (i.e. association URI).
48
+ ##
49
+ def keys
50
+ @key || value.id
51
+ end
46
52
 
47
53
  private
48
54
 
@@ -10,8 +10,12 @@ module RDFMapper
10
10
  # objects as appropriate.
11
11
  ##
12
12
  def replace(objects)
13
- new_objects = filter(objects.to_a)
14
- return @value if new_objects.empty?
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
- @value
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
- raise NotImplementedError, '`find` not yet implemented' # TODO
75
+ def find(*args)
76
+ @association.find(*args).from(value)
73
77
  end
74
78
 
75
79
  ##
76
- # Returns one or more new objects of the collection type that
77
- # have been instantiated with attributes and linked to this object
78
- # through a foreign key, but have not yet been saved.
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
- raise NotImplementedError, '`build` not yet implemented' # TODO
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
- raise NotImplementedError, '`create` not yet implemented' # TODO
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
- @value ||= []
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
  ##
@@ -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, id)
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(id, attributes = {})
320
- instance = find(id)
321
- instance.nil? ? create(id, attributes) : instance
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 [RDF::URI] object's ID
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.merge(@arbitrary)
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 = RDF::URI.new(value.to_s)
628
+ @id = value.to_s
592
629
  end
593
630
 
594
631
  ##
@@ -12,7 +12,7 @@ module RDFMapper
12
12
  ##
13
13
  # Checks if property has default (nil) value.
14
14
  #
15
- # @params [Boolean]
15
+ # @param [Boolean]
16
16
  ##
17
17
  def new?
18
18
  @new
@@ -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
  #
@@ -18,10 +18,10 @@ module RDFMapper
18
18
  if @att == :id
19
19
  return @att
20
20
  end
21
- unless att = @cls.has?(@att)
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
  ##
@@ -24,14 +24,29 @@ module RDFMapper
24
24
  end
25
25
 
26
26
  ##
27
- # Sets data adapter for this loader. This will override default model adapter.
27
+ # Sets data adapter or collection.
28
28
  #
29
- # @param [Symbol] adapter (:rails, :sparql, :rest)
30
- # @param [Hash] options options to pass on to the adapter constructor
31
- # @return [Object] adapter instance
32
- ##
33
- def from(adapter, options = {})
34
- @adapter = RDFMapper::Adapters.register(adapter, @cls, options)
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
  ##
@@ -46,13 +46,21 @@ module RDFMapper
46
46
  # In addition to the original method, preloads the model.
47
47
  ##
48
48
  def [](name)
49
- super || (@loaded ? nil : load[name])
49
+ @arbitrary[name] || (@loaded ? super(name) : load[name])
50
50
  end
51
51
 
52
52
  ##
53
- # Returns a hash of all the attributes with their names as keys and
54
- # the attributes' values as values. If model is unloaded, it will
55
- # preload it before returning its attributes.
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
  ##
@@ -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
- [{ :subject => target,
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
- - 2
9
- version: 0.0.2
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-26 00:00:00 +01:00
17
+ date: 2010-05-28 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency