active-fedora 6.4.4 → 6.4.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9682552f64d1274de9b4de8f26e12dc1ab04cab5
4
- data.tar.gz: 0267bbbfcd15b12ab6593620aebab8e2e6322274
3
+ metadata.gz: 5c3b9301740101d4e6c50bd6d5ce3f8e6bdf5d48
4
+ data.tar.gz: 84fed4e80fc0a7d1f5d2123836867f804427f797
5
5
  SHA512:
6
- metadata.gz: 8fdd12fb3660f58afca86fa8f488d3da34db1e36ceb55b76d3cda5f33f6a87a2b668bbcc6841d07a7d62f14d32fb77e61811fad3a29cd1a268175b30dd536587
7
- data.tar.gz: 96459b1261137d65d9f64e2dab39587aac41466f958b943da81a19799ec7d7f6a343b353332984d43de296d161172861fdea152854811056f04d2d1a64b60e85
6
+ metadata.gz: 70b1bcb60f130c770e54866396de53f876d3529b0befce9bcfc180fe6b2540630c7b4df492057fe7dd4e2406b3cd35ecb9cd1a675af3f3ff0591be4716d752ba
7
+ data.tar.gz: d66329975f4374c0a46102235195760b1ac72ef7bddba684f9bbe6af16d2b2fc65cec3f7c526bed7870b0b38cb4a38569d480fce812b35b02e146306e5ec1543
@@ -1,3 +1,132 @@
1
+ v6.4.5 (2013-08-05)
2
+
3
+ Clear rdf lists and proxies [Justin Coyne]
4
+
5
+ When defining rdf terminologies you should be able to say 'multivalue: false'
6
+ [Justin Coyne]
7
+
8
+ Created RdfList#to_ary [Justin Coyne]
9
+
10
+ Define UNASSIGNABLE_KEYS for RdfList.assign_nested_attributes... [Justin Coyne]
11
+
12
+ Added RdfList.each [Justin Coyne]
13
+
14
+ Cache the tail node in an RDFList [Justin Coyne]
15
+
16
+ class_from_string should have an exit condition when the class can't be found
17
+ [Justin Coyne]
18
+
19
+ Add a warning letting you know you may have already registered this RDF.type
20
+ [Justin Coyne]
21
+
22
+ Rdf lists should only have one RDF.rest node [Justin Coyne]
23
+
24
+ RDF lists should be able to accept nested attributes as a hash [Justin Coyne]
25
+
26
+ Clean up YARD doc warnings [Justin Coyne]
27
+
28
+ An rdf node should be able to set rdf:about [Justin Coyne]
29
+
30
+ Remove RdfObject#get_values, it's inherited [Justin Coyne]
31
+
32
+
33
+ v6.4.4 (2013-07-29)
34
+
35
+ Bumping to version 6.4.4 [Jeremy Friesen]
36
+
37
+ Use get_config_path to get the path for the predicate_mappings.yml
38
+ [Justin Coyne]
39
+
40
+ has_and_belongs_to_many can have more than 10 results. [Justin
41
+ Coyne]
42
+
43
+ Filters belongs_to associations by :class_name if specified [Simon
44
+ Lamb]
45
+
46
+ Don't reindex fedora-system objects in reindex_everything [Justin
47
+ Coyne]
48
+
49
+ Adding "An ActiveModel" shared behavior [Jeremy Friesen]
50
+
51
+ Allow query parameter AF.reindex_everything [Jeremy Friesen]
52
+
53
+ Updating CONTRIBUTING.md as per Hydra v6.0.0 [Jeremy Friesen]
54
+
55
+ The example test should look for Base.exists?() rather than checking
56
+ to see that an ObjectNotFound error is raised. [Justin Coyne]
57
+
58
+
59
+ v6.4.3 (2013-07-16)
60
+
61
+ class_from_string should find sibiling classes [Justin Coyne]
62
+
63
+ Ensuring that AF::Base.find("") raises exception [Jeremy Friesen]
64
+
65
+ Added ActiveFedora::SolrService.lazy_reify_solr_results to provide
66
+ lazy (Ruby 1.9-compatible) reification alternative to .reify_solr_results.
67
+ ActiveFedora::SolrService.reify_solr_results refactored, extracting single
68
+ reification to .reify_solr_result. Supplied missing test for :load_from_solr
69
+ option to .reify_solr_results [David Chandek-Stark]
70
+
71
+ Adding mailmap for improving changelog generation [Jeremy Friesen]
72
+
73
+ Tidying up how ActiveFedora::Base.exists? behaves [Jeremy Friesen]
74
+
75
+ Tidying up hash key access of AF::Model [Jeremy Friesen]
76
+
77
+ Fixed test for equality within OmDatastream.changed? [Justin Coyne]
78
+
79
+ mock() and stub() are deprecated. Switched to double() [Justin
80
+ Coyne]
81
+
82
+ Remove all serialized foxml in favor of programmatic creation of
83
+ fixtures in preperation for Fedora 4; One broken test revealed dealing with
84
+ managed om datastreams [Chris Colvard]
85
+
86
+
87
+ v6.4.2 (2013-07-10)
88
+
89
+ Bumping version to 6.4.2 [Jeremy Friesen]
90
+
91
+ In activerecord 4.0 the update() method accepts arguments. Conform
92
+ to that interface. [Justin Coyne]
93
+
94
+
95
+ v6.4.1 (2013-07-10)
96
+
97
+ Change generator template to not use named argument 'name' [Justin
98
+ Coyne]
99
+
100
+ Infer the property on has_many. Fixes #142 [Justin Coyne]
101
+
102
+ Added new_record? method to Rdf nodes [Justin Coyne]
103
+
104
+ Test the behavior when the node can't be found [Justin Coyne]
105
+
106
+ Rdf nested attributes should accept hashes [Justin Coyne]
107
+
108
+ Added :type to ActiveFedora::QualifiedDublinCoreDatastream::DCTERMS.
109
+ Presumably this field was excluded due to Object#type from Ruby 1.8. Since AF
110
+ currently requires >= Ruby 1.9.3, it appears safe to add this DC 1.1 element.
111
+ [David Chandek-Stark]
112
+
113
+ Removed outdated comment that OmDatastream is just an alias for
114
+ NokogiriDatastream [David Chandek-Stark]
115
+
116
+ Added :path option to
117
+ ActiveFedora::QualifiedDublinCoreDatastream#field in order to support, for
118
+ example, mapping the term :dc_type to <dcterms:type> (:type is excluded from
119
+ ActiveFedora::QualifiedDublinCoreDatastream::DCTERMS). Implementation simply
120
+ adds :path (even if nil) to OM::XML::Term.new since initializer falls back to
121
+ field name anyway. [David Chandek-Stark]
122
+
123
+ Generate a datastream in addition to the model [Justin Coyne]
124
+
125
+ Autoload classes in app/models/datastreams [Justin Coyne]
126
+
127
+ Remove unnecessary require of 'active_fedora/base' in model template [Justin Coyne]
128
+
129
+
1
130
  6.4.0 (2013-07-01)
2
131
 
3
132
  Removing experimental designation, tidying-up the code [Adam Wead]
@@ -22,7 +22,6 @@ module ActiveFedora #:nodoc:
22
22
  class AssociationTypeMismatch < RuntimeError; end # :nodoc:
23
23
  class UnregisteredPredicateError < RuntimeError; end # :nodoc:
24
24
  class RecordNotSaved < RuntimeError; end # :nodoc:
25
- class RecordNotFound < RuntimeError; end # :nodoc:
26
25
 
27
26
 
28
27
  eager_autoload do
@@ -161,7 +160,9 @@ module ActiveFedora #:nodoc:
161
160
  container_class = container_class.name if container_class.is_a? Module
162
161
  container_parts = container_class.split('::')
163
162
  (container_parts + class_name.split('::')).flatten.inject(Kernel) do |mod, class_name|
164
- if mod.const_defined? class_name.to_sym
163
+ if mod == Kernel
164
+ Object.const_get(class_name)
165
+ elsif mod.const_defined? class_name.to_sym
165
166
  mod.const_get(class_name)
166
167
  else
167
168
  container_parts.pop
@@ -103,8 +103,8 @@ module ActiveFedora
103
103
  end
104
104
 
105
105
  # Reveal if the delegated field is unique or not
106
- # @params [Symbol] field the field to query
107
- # @returns [Boolean]
106
+ # @param [Symbol] field the field to query
107
+ # @return [Boolean]
108
108
  def unique?(field)
109
109
  delegates[field][:unique]
110
110
  end
@@ -87,7 +87,7 @@ module ActiveFedora
87
87
  end
88
88
 
89
89
  # Using the fedora search (not solr), get every object and reindex it.
90
- # @param [String] a query string that conforms to the query param format
90
+ # @param [String] query a string that conforms to the query param format
91
91
  # of the underlying search's API
92
92
  def reindex_everything(query = nil)
93
93
  connections.each do |conn|
@@ -2,5 +2,6 @@ module ActiveFedora
2
2
  module Rdf
3
3
  extend ActiveSupport::Autoload
4
4
  autoload :NestedAttributes
5
+ autoload :NodeConfig
5
6
  end
6
7
  end
@@ -10,10 +10,10 @@ module ActiveFedora
10
10
 
11
11
  private
12
12
 
13
- UNASSIGNABLE_KEYS = %w( id _destroy )
13
+ UNASSIGNABLE_KEYS = %w(_destroy )
14
14
 
15
- # @params [Symbol] association_name
16
- # @params [Hash, Array] attributes_collection
15
+ # @param [Symbol] association_name
16
+ # @param [Hash, Array] attributes_collection
17
17
  # @example
18
18
  #
19
19
  # assign_nested_attributes_for_collection_association(:people, {
@@ -39,7 +39,7 @@ module ActiveFedora
39
39
  # TODO
40
40
  #check_record_limit!(options[:limit], attributes_collection)
41
41
 
42
- if attributes_collection.is_a?(Hash)# || attributes_collection.is_a?(String)
42
+ if attributes_collection.is_a?(Hash)
43
43
  attributes_collection = attributes_collection.values
44
44
  end
45
45
 
@@ -48,15 +48,13 @@ module ActiveFedora
48
48
  attributes_collection.each do |attributes|
49
49
  attributes = attributes.with_indifferent_access
50
50
 
51
- if attributes['id'].blank?
52
- attributes = attributes.with_indifferent_access
53
- association.build(attributes.except(*UNASSIGNABLE_KEYS))
54
- elsif existing_record = association.detect { |record| record.rdf_subject.to_s == attributes['id'].to_s }
51
+ if attributes['id'] && existing_record = association.detect { |record| record.rdf_subject.to_s == attributes['id'].to_s }
55
52
  if !call_reject_if(association_name, attributes)
56
53
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
57
54
  end
58
55
  else
59
- raise_nested_attributes_record_not_found(association_name, attributes['id'].to_s)
56
+ attributes = attributes.with_indifferent_access
57
+ association.build(attributes.except(*UNASSIGNABLE_KEYS))
60
58
  end
61
59
  end
62
60
  end
@@ -68,10 +66,6 @@ module ActiveFedora
68
66
  record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy
69
67
  end
70
68
 
71
- def raise_nested_attributes_record_not_found(association_name, record_id)
72
- raise RecordNotFound, "Couldn't find #{association_name} with ID=#{record_id} for #{self.class.name} with ID=#{rdf_subject.to_s}"
73
- end
74
-
75
69
  def call_reject_if(association_name, attributes)
76
70
  return false if has_destroy_flag?(attributes)
77
71
  case callback = self.nested_attributes_options[association_name][:reject_if]
@@ -0,0 +1,41 @@
1
+ module ActiveFedora
2
+ module Rdf
3
+ class NodeConfig
4
+ attr_accessor :predicate, :class_name, :type, :behaviors, :multivalue
5
+
6
+ def initialize(predicate, args={})
7
+ self.predicate = predicate
8
+ self.class_name = args.delete(:class_name)
9
+ self.multivalue = args.delete(:multivalue) { true }
10
+ raise ArgumentError, "Invalid arguments for Rdf Node configuration: #{args} on #{predicate}" unless args.empty?
11
+ end
12
+
13
+
14
+ def with_index (&block)
15
+ # needed for solrizer integration
16
+ iobj = IndexObject.new
17
+ yield iobj
18
+ self.type = iobj.data_type
19
+ self.behaviors = iobj.behaviors
20
+ end
21
+
22
+ # this enables a cleaner API for solr integration
23
+ class IndexObject
24
+ attr_accessor :data_type, :behaviors
25
+ def initialize
26
+ @behaviors = []
27
+ @data_type = :string
28
+ end
29
+ def as(*args)
30
+ @behaviors = args
31
+ end
32
+ def type(sym)
33
+ @data_type = sym
34
+ end
35
+ def defaults
36
+ :noop
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -141,8 +141,8 @@ module ActiveFedora
141
141
 
142
142
  name, config = self.class.config_for_predicate(predicate)
143
143
  next unless config
144
- type = config[:type]
145
- behaviors = config[:behaviors]
144
+ type = config.type
145
+ behaviors = config.behaviors
146
146
  next unless type and behaviors
147
147
  field_map[name] ||= {:values => [], :type => type, :behaviors => behaviors}
148
148
  field_map[name][:values] << value.to_s
@@ -5,14 +5,22 @@ module ActiveFedora
5
5
 
6
6
  attr_reader :graph, :subject
7
7
 
8
+ # RdfList is a node of a linked list structure.
9
+ # The RDF.first predicate points to the contained object
10
+ # The RDF.rest predicate points to the next node in the list or
11
+ # RDF.nil if this is the final node.
12
+ # @see http://www.w3.org/TR/rdf-schema/#ch_list
8
13
  def initialize(graph, subject)
9
14
  @graph = graph
10
15
  @subject = subject
11
16
  first = graph.query([subject, RDF.first, nil]).first
17
+ last = graph.query([subject, RDF.rest, nil]).first
12
18
  graph.insert([subject, RDF.first, RDF.nil]) unless first
13
- graph.insert([subject, RDF.rest, RDF.nil])
19
+ graph.insert([subject, RDF.rest, RDF.nil]) unless last
14
20
  end
15
-
21
+
22
+ UNASSIGNABLE_KEYS = %w(_destroy )
23
+
16
24
  # Override assign_nested_attributes
17
25
  def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
18
26
  options = self.nested_attributes_options[association_name]
@@ -20,24 +28,26 @@ module ActiveFedora
20
28
  # TODO
21
29
  #check_record_limit!(options[:limit], attributes_collection)
22
30
 
23
- if attributes_collection.is_a?(Hash) || attributes_collection.is_a?(String)
24
- attributes_collection = [attributes_collection]
31
+ if attributes_collection.is_a?(Hash)
32
+ attributes_collection = attributes_collection.values
25
33
  end
26
34
 
27
35
  association = self.send(association_name)
28
36
 
29
37
  original_length_of_list = self.size
30
38
  attributes_collection.each_with_index do |attributes, index|
31
- if attributes.instance_of? Hash
32
- attributes = attributes.with_indifferent_access
33
- minted_node = association.mint_node(attributes.except(*UNASSIGNABLE_KEYS))
34
- else
35
- minted_node = association.mint_node(attributes)
36
- end
39
+ attributes = attributes.with_indifferent_access
40
+ minted_node = association.mint_node(attributes.except(*UNASSIGNABLE_KEYS))
37
41
  self[original_length_of_list+index] = minted_node
38
42
  end
39
43
  end
40
44
 
45
+
46
+ # Override the method from RdfNode, enabling us to insert into the list.
47
+ def insert_child(predicate, node)
48
+ self[size] = node
49
+ end
50
+
41
51
  def rdf_subject
42
52
  subject
43
53
  end
@@ -54,11 +64,48 @@ module ActiveFedora
54
64
  idx == 0 ? head.value=value : tail_or_create(idx-1).value=value
55
65
  end
56
66
 
67
+ def clear(first_element=true)
68
+ # Remove the pointed at element
69
+ v = graph.query([subject, RDF.first, nil]).first
70
+ # TODO - Recursive delete
71
+ graph.delete([v.object, nil, nil])
72
+
73
+ # Remove the tail
74
+ tail.clear(false) if tail
75
+ # clear the cache
76
+ @tail = nil
77
+ graph.delete([subject, nil, nil])
78
+ if first_element
79
+ # Re-add first/rest predicates if its the first node
80
+ graph.insert([subject, RDF.first, RDF.nil])
81
+ graph.insert([subject, RDF.rest, RDF.nil])
82
+ end
83
+ end
84
+
85
+ def each &block
86
+ yield(head.value)
87
+ tail.each(&block) if tail
88
+ end
89
+
90
+ def to_ary
91
+ if empty?
92
+ []
93
+ elsif tail
94
+ [head.value] + tail.to_ary
95
+ else
96
+ [head.value]
97
+ end
98
+ end
99
+
100
+ def empty?
101
+ !tail && graph.query([subject, RDF.first, RDF.nil]).first
102
+ end
103
+
57
104
  def size
58
- if tail
59
- tail.size + 1
60
- elsif graph.query([subject, RDF.first, RDF.nil]).first
105
+ if empty?
61
106
  0
107
+ elsif tail
108
+ tail.size + 1
62
109
  else
63
110
  1
64
111
  end
@@ -70,7 +117,9 @@ module ActiveFedora
70
117
 
71
118
  def value
72
119
  v = graph.query([subject, RDF.first, nil]).first
73
- return v.object if v.object.uri?
120
+ if v.object.uri?
121
+ return v.object == RDF.nil ? nil : v.object
122
+ end
74
123
  if v.object.resource?
75
124
  type = graph.query([v.object, RDF.type, nil]).first
76
125
  return ActiveFedora::RdfNode.rdf_registry[type.object].new(graph, v.object)
@@ -92,24 +141,22 @@ module ActiveFedora
92
141
  end
93
142
 
94
143
  def tail
144
+ return @tail if @tail
95
145
  rest = graph.query([subject, RDF.rest, nil]).first
96
146
  return if rest.object == RDF.nil
97
- self.class.new(graph, rest.object)
147
+ @tail = self.class.new(graph, rest.object)
98
148
  end
99
149
 
100
150
  def tail_or_create(idx)
101
- rest = graph.query([subject, RDF.rest, nil]).first
102
- obj = if rest.object != RDF.nil
103
- self.class.new(graph, rest.object)
104
- else
151
+ unless tail
105
152
  #add a tail
106
153
  graph.delete([subject, RDF.rest, RDF.nil])
107
- tail = RDF::Node.new
108
- graph.insert([subject, RDF.rest, tail])
109
- self.class.new(graph, tail)
154
+ tail_node = RDF::Node.new
155
+ graph.insert([subject, RDF.rest, tail_node])
156
+ @tail = self.class.new(graph, tail_node)
110
157
  end
111
158
 
112
- idx == 0 ? obj : obj.tail_or_create(idx-1)
159
+ idx == 0 ? @tail : @tail.tail_or_create(idx-1)
113
160
  end
114
161
  end
115
162
  end
@@ -44,14 +44,14 @@ module ActiveFedora
44
44
  # @param [Symbol] term the term to get the values for
45
45
  def get_values(subject, term)
46
46
  options = config_for_term_or_uri(term)
47
- predicate = options[:predicate]
47
+ predicate = options.predicate
48
48
  @target ||= {}
49
49
  @target[term.to_s] ||= TermProxy.new(self, subject, predicate, options)
50
50
  end
51
51
 
52
52
  def target_class(predicate)
53
53
  _, conf = self.class.config_for_predicate(predicate)
54
- class_name = conf[:class_name]
54
+ class_name = conf.class_name
55
55
  return nil unless class_name
56
56
  ActiveFedora.class_from_string(class_name, self.class)
57
57
  end
@@ -74,11 +74,11 @@ module ActiveFedora
74
74
 
75
75
  # if there are any existing statements with this predicate, replace them
76
76
  # @param [RDF::URI] subject the subject to insert into the graph
77
- # @param [Symbol, RDF::URI] predicate the predicate to insert into the graph
77
+ # @param [Symbol, RDF::URI] term the term to insert into the graph
78
78
  # @param [Array,#to_s] values the value/values to insert into the graph
79
79
  def set_value(subject, term, values)
80
80
  options = config_for_term_or_uri(term)
81
- predicate = options[:predicate]
81
+ predicate = options.predicate
82
82
  values = Array(values)
83
83
 
84
84
  remove_existing_values(subject, predicate, values)
@@ -160,10 +160,15 @@ module ActiveFedora
160
160
  graph.insert([subject, predicate, args])
161
161
  end
162
162
 
163
+ def insert_child(predicate, node)
164
+ graph.insert([rdf_subject, predicate, node.rdf_subject])
165
+ end
166
+
167
+
163
168
  def config_for_term_or_uri(term)
164
169
  case term
165
170
  when RDF::URI
166
- self.class.config.each { |k, v| return v if v[:predicate] == term}
171
+ self.class.config.each { |k, v| return v if v.predicate == term}
167
172
  else
168
173
  self.class.config[term.to_sym]
169
174
  end
@@ -172,7 +177,7 @@ module ActiveFedora
172
177
  # @param [Symbol, RDF::URI] term predicate the predicate to insert into the graph
173
178
  def find_predicate(term)
174
179
  conf = config_for_term_or_uri(term)
175
- conf ? conf[:predicate] : nil
180
+ conf ? conf.predicate : nil
176
181
  end
177
182
 
178
183
  def query subject, predicate, &block
@@ -248,45 +253,14 @@ module ActiveFedora
248
253
  def method_missing(name, *args, &block)
249
254
  args = args.first if args.respond_to? :first
250
255
  raise "mapping must specify RDF vocabulary as :in argument" unless args.has_key? :in
251
- vocab = args[:in]
252
- field = args.fetch(:to, name).to_sym
253
- class_name = args[:class_name]
256
+ vocab = args.delete(:in)
257
+ field = args.delete(:to) {name}.to_sym
254
258
  raise "Vocabulary '#{vocab.inspect}' does not define property '#{field.inspect}'" unless vocab.respond_to? field
255
- indexing = false
256
- if block_given?
257
- # needed for solrizer integration
258
- indexing = true
259
- iobj = IndexObject.new
260
- yield iobj
261
- data_type = iobj.data_type
262
- behaviors = iobj.behaviors
263
- end
264
- @parent.config[name] = {:predicate => vocab.send(field) }
265
- # stuff data_type and behaviors in there for to_solr support
266
- if indexing
267
- @parent.config[name][:type] = data_type
268
- @parent.config[name][:behaviors] = behaviors
259
+ @parent.config[name] = Rdf::NodeConfig.new(vocab.send(field), args).tap do |config|
260
+ config.with_index(&block) if block_given?
269
261
  end
270
- @parent.config[name][:class_name] = class_name if class_name
271
262
  end
272
263
 
273
- # this enables a cleaner API for solr integration
274
- class IndexObject
275
- attr_accessor :data_type, :behaviors
276
- def initialize
277
- @behaviors = []
278
- @data_type = :string
279
- end
280
- def as(*args)
281
- @behaviors = args
282
- end
283
- def type(sym)
284
- @data_type = sym
285
- end
286
- def defaults
287
- :noop
288
- end
289
- end
290
264
  end
291
265
 
292
266
  module ClassMethods
@@ -315,8 +289,9 @@ module ActiveFedora
315
289
  def rdf_type(uri_or_string=nil)
316
290
  if uri_or_string
317
291
  uri = uri_or_string.kind_of?(RDF::URI) ? uri_or_string : RDF::URI.new(uri_or_string)
318
- self.config[:type] = {predicate: RDF.type}
292
+ self.config[:type] = Rdf::NodeConfig.new(RDF.type)
319
293
  @rdf_type = uri
294
+ logger.warn "Duplicate RDF Class. Trying to register #{self} for #{uri} but it is already registered for #{ActiveFedora::RdfNode.rdf_registry[uri]}" if ActiveFedora::RdfNode.rdf_registry.key? uri
320
295
  ActiveFedora::RdfNode.rdf_registry[uri] = self
321
296
  end
322
297
  @rdf_type
@@ -324,7 +299,7 @@ module ActiveFedora
324
299
 
325
300
  def config_for_predicate(predicate)
326
301
  config.each do |term, value|
327
- return term, value if value[:predicate] == predicate
302
+ return term, value if value.predicate == predicate
328
303
  end
329
304
  return nil
330
305
  end
@@ -17,21 +17,36 @@ module ActiveFedora
17
17
  end
18
18
 
19
19
 
20
- def build(attributes=nil)
20
+ def build(attributes={})
21
21
  node = mint_node(attributes)
22
- parent.graph.insert([subject, predicate, node.rdf_subject])
22
+ parent.insert_child(predicate, node)
23
23
  reset!
24
24
  new_node = target.find { |n| n.rdf_subject == node.rdf_subject}
25
+ new_node = node unless new_node #if it's a list, the find doesn't work, just use the new node
25
26
  new_node.new_record = true
26
27
  new_node
27
28
  end
28
29
 
30
+ # Remove all matching nodes from the graph
31
+ def clear
32
+ parent.query(subject, predicate).each do |solution|
33
+ # TODO - Recursive delete
34
+ # Delete everythign we're pointing at.
35
+ parent.graph.delete([solution.value, nil, nil]) if solution.value.uri?
36
+ end
37
+ # Delete all the assertions about this object
38
+ parent.graph.delete([subject, nil, nil])
39
+ reset!
40
+ end
41
+
29
42
  def reset!
30
43
  @target = nil
31
44
  end
32
45
 
33
- def mint_node(attributes=nil)
34
- new_subject = RDF::Node.new
46
+ # @param [Hash] attributes
47
+ # @option attributes id the rdf subject to use for the node, if omitted the new node will be a b-node
48
+ def mint_node(attributes)
49
+ new_subject = attributes.key?('id') ? RDF::URI.new(attributes.delete('id')) : RDF::Node.new
35
50
  return parent.target_class(predicate).new(parent.graph, new_subject).tap do |node|
36
51
  node.attributes = attributes if attributes
37
52
  end
@@ -55,30 +70,31 @@ module ActiveFedora
55
70
  @target ||= load_values
56
71
  end
57
72
 
73
+ # Get the values off of the rdf nodes this proxy targets
58
74
  def load_values
59
75
  values = []
60
76
 
61
77
  parent.query(subject, predicate).each do |solution|
62
78
  v = solution.value
63
79
  v = v.to_s if v.is_a? RDF::Literal
64
- if options[:type] == :date
80
+ if options.type == :date
65
81
  v = Date.parse(v)
66
82
  end
67
83
  # If the user provided options[:class_name], we should query to make sure this
68
84
  # potential solution is of the right RDF.type
69
- if options[:class_name]
85
+ if options.class_name
70
86
  klass = class_from_rdf_type(v)
71
- values << v if klass == ActiveFedora.class_from_string(options[:class_name], parent.class)
87
+ values << v if klass == ActiveFedora.class_from_string(options.class_name, parent.class)
72
88
  else
73
89
  values << v
74
90
  end
75
91
  end
76
92
 
77
- if options[:class_name]
93
+ if options.class_name
78
94
  values = values.map{ |found_subject| class_from_rdf_type(found_subject).new(parent.graph, found_subject)}
79
95
  end
80
96
 
81
- values
97
+ options.multivalue ? values : values.first
82
98
  end
83
99
 
84
100
  private
@@ -91,7 +107,7 @@ module ActiveFedora
91
107
  # Two classes may be valid for the same predicate (e.g. hasMember)
92
108
  # If no RDF.type assertion is found, fall back to using target_class
93
109
  def class_from_rdf_type(subject)
94
- unless subject.kind_of?(RDF::Node)
110
+ unless subject.kind_of?(RDF::Node) || subject.kind_of?(RDF::URI)
95
111
  raise ArgumentError, "Expected the value of #{predicate} to be an RDF object but it is a #{subject.class} #{subject.inspect}"
96
112
  end
97
113
  q = RDF::Query.new do
@@ -20,11 +20,6 @@ module ActiveFedora
20
20
  insert_type_assertion
21
21
  end
22
22
 
23
- def get_values(subject, predicate)
24
- predicate = find_predicate(predicate) unless predicate.kind_of? RDF::URI
25
- return TermProxy.new(@graph, @subject, predicate)
26
- end
27
-
28
23
  private
29
24
 
30
25
  def insert_type_assertion
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "6.4.4"
2
+ VERSION = "6.4.5"
3
3
  end
@@ -49,16 +49,24 @@ describe "Nesting attribute behavior of RDFDatastream" do
49
49
  accepts_nested_attributes_for :elementList, :extraProperty
50
50
  end
51
51
  class ElementList
52
- include ActiveFedora::RdfObject
52
+ include ActiveFedora::RdfList
53
53
  rdf_type DummyMADS.elementList
54
54
  map_predicates do |map|
55
- map.topicElement(in: DummyMADS, to: "TopicElement")
55
+ map.topicElement(in: DummyMADS, to: "TopicElement", :class_name => "MadsTopicElement")
56
56
  map.temporalElement(in: DummyMADS, to: "TemporalElement")
57
57
  map.fullNameElement(in: DummyMADS, to: "FullNameElement")
58
58
  map.dateNameElement(in: DummyMADS, to: "DateNameElement")
59
59
  map.nameElement(in: DummyMADS, to: "NameElement")
60
60
  map.elementValue(in: DummyMADS)
61
61
  end
62
+ accepts_nested_attributes_for :topicElement
63
+ end
64
+ class MadsTopicElement
65
+ include ActiveFedora::RdfObject
66
+ rdf_type DummyMADS.TopicElement
67
+ map_predicates do |map|
68
+ map.elementValue(in: DummyMADS)
69
+ end
62
70
  end
63
71
  end
64
72
  end
@@ -74,13 +82,13 @@ describe "Nesting attribute behavior of RDFDatastream" do
74
82
  '0' =>
75
83
  {
76
84
  elementList_attributes: [{
77
- topicElement:"Cosmology"
85
+ topicElement_attributes: [{elementValue:"Cosmology"}]
78
86
  }]
79
87
  },
80
88
  '1' =>
81
89
  {
82
90
  elementList_attributes: [{
83
- topicElement:"Quantum Behavior"
91
+ topicElement_attributes: {'0' => {elementValue:"Quantum Behavior"}}
84
92
  }]
85
93
  }
86
94
  },
@@ -97,6 +105,21 @@ describe "Nesting attribute behavior of RDFDatastream" do
97
105
  }
98
106
  end
99
107
 
108
+ describe "on lists" do
109
+ subject { ComplexRDFDatastream::PersonalName.new(RDF::Graph.new) }
110
+ it "should accept a hash" do
111
+ subject.elementList_attributes = [{ topicElement_attributes: {'0' => { elementValue:"Quantum Behavior" }, '1' => { elementValue:"Wave Function" }}}]
112
+ subject.elementList.first[0].elementValue.should == ["Quantum Behavior"]
113
+ subject.elementList.first[1].elementValue.should == ["Wave Function"]
114
+
115
+ end
116
+ it "should accept an array" do
117
+ subject.elementList_attributes = [{ topicElement_attributes: [{ elementValue:"Quantum Behavior" }, { elementValue:"Wave Function" }]}]
118
+ subject.elementList.first[0].elementValue.should == ["Quantum Behavior"]
119
+ subject.elementList.first[1].elementValue.should == ["Wave Function"]
120
+ end
121
+ end
122
+
100
123
  it "should create nested objects" do
101
124
  # Replace the graph's contents with the Hash
102
125
  subject.attributes = params[:myResource]
@@ -110,8 +133,8 @@ describe "Nesting attribute behavior of RDFDatastream" do
110
133
  # elem_list = topic.elementList.build
111
134
  # elem_list.fullNameElement = 'Cosmology'
112
135
 
113
- subject.topic.first.elementList.first.topicElement.should == ["Cosmology"]
114
- subject.topic[1].elementList.first.topicElement.should == ["Quantum Behavior"]
136
+ subject.topic[0].elementList.first[0].elementValue.should == ["Cosmology"]
137
+ subject.topic[1].elementList.first[0].elementValue.should == ["Quantum Behavior"]
115
138
  subject.personalName.first.elementList.first.fullNameElement.should == ["Jefferson, Thomas"]
116
139
  subject.personalName.first.elementList.first.dateNameElement.should == ["1743-1826"]
117
140
  end
@@ -155,10 +178,9 @@ describe "Nesting attribute behavior of RDFDatastream" do
155
178
  subject.parts.map{|p| p.label.first}.should == ['Alternator', 'Universal Joint', 'Transmission', 'Oil Pump']
156
179
 
157
180
  end
158
- it "should raise an error when the object isn't found" do
159
- expect {
160
- subject.parts_attributes= [{id: '_:g70192865051320', label: "Universal Joint"}]
161
- }.to raise_error ActiveFedora::RecordNotFound
181
+ it "create a new object when the id is provided" do
182
+ subject.parts_attributes= [{id: 'http://example.com/part#1', label: "Universal Joint"}]
183
+ subject.parts.last.rdf_subject.should == 'http://example.com/part#1'
162
184
  end
163
185
  end
164
186
  end
@@ -121,5 +121,11 @@ describe ActiveFedora do
121
121
  it "should find sibling classes" do
122
122
  ActiveFedora.class_from_string("SiblingClass", ParentClass::OtherSiblingClass).should == ParentClass::SiblingClass
123
123
  end
124
+
125
+ it "should raise a NameError if the class isn't found" do
126
+ expect {
127
+ ActiveFedora.class_from_string("FooClass", ParentClass::OtherSiblingClass)
128
+ }.to raise_error NameError, "uninitialized constant FooClass"
129
+ end
124
130
  end
125
131
  end
@@ -9,7 +9,8 @@ describe ActiveFedora::RDFDatastream do
9
9
  before do
10
10
  class MyDatastream < ActiveFedora::NtriplesRDFDatastream
11
11
  map_predicates do |map|
12
- map.title(:in => RDF::DC)
12
+ map.title(in: RDF::DC)
13
+ map.description(in: RDF::DC, multivalue: false)
13
14
  end
14
15
  end
15
16
  class MyObj < ActiveFedora::Base
@@ -31,12 +32,25 @@ describe ActiveFedora::RDFDatastream do
31
32
  end
32
33
 
33
34
  it "should allow asserting an empty string" do
34
- @obj.descMetadata.title = ['']
35
- @obj.descMetadata.title.should == ['']
35
+ subject.title = ['']
36
+ subject.title.should == ['']
37
+ end
38
+
39
+ describe "when multivalue: false" do
40
+ it "should return single values" do
41
+ subject.description = 'my description'
42
+ subject.description.should == 'my description'
43
+ end
44
+ end
45
+
46
+ it "should clear stuff" do
47
+ subject.title = ['one', 'two', 'three']
48
+ subject.title.clear
49
+ subject.graph.query([subject.rdf_subject, RDF::DC.title, nil]).first.should be_nil
36
50
  end
37
51
 
38
52
  it "should have a list of fields" do
39
- MyDatastream.fields.should == [:title]
53
+ MyDatastream.fields.should == [:title, :description]
40
54
  end
41
55
  end
42
56
  end
@@ -78,6 +78,9 @@ describe ActiveFedora::RdfList do
78
78
  topic.elementList.first[0].elementValue.should == ["Baseball"]
79
79
  topic.elementList.first[1].should be_kind_of(TopicElement)
80
80
  topic.elementList.first[1].elementValue.should == ["Football"]
81
+
82
+ # only one rdf:rest rdf:nil
83
+ topic.graph.query([nil, RDF.rest, RDF.nil]).size.should == 1
81
84
  end
82
85
  it "should insert new nodes of varying types into RdfLists (rather than calling .build)" do
83
86
  # It's Not clear what the syntax should be when an RDF list contains multiple types of sub-nodes.
@@ -107,4 +110,4 @@ describe ActiveFedora::RdfList do
107
110
  topic.elementList.first[3].elementValue.should == ["Twentieth Century"]
108
111
  end
109
112
  end
110
- end
113
+ end
@@ -16,6 +16,11 @@ describe ActiveFedora::RdfList do
16
16
  end
17
17
  class List
18
18
  include ActiveFedora::RdfList
19
+ map_predicates do |map|
20
+ map.topicElement(:in=> MADS, :to =>"TopicElement", :class_name => "TopicElement")
21
+ map.temporalElement(:in=> MADS, :to =>"TemporalElement", :class_name => "TemporalElement")
22
+ end
23
+
19
24
  class TopicElement
20
25
  include ActiveFedora::RdfObject
21
26
  rdf_type MADS.TopicElement
@@ -100,6 +105,33 @@ END
100
105
 
101
106
  end
102
107
 
108
+ describe "an empty list" do
109
+ subject { DemoList.new(double('inner object', :pid=>'foo', :new? =>true)).elementList.build }
110
+ it "should have to_ary" do
111
+ subject.to_ary.should == []
112
+ end
113
+ end
114
+
115
+ describe "a list that has a constructed element" do
116
+ let(:ds) { DemoList.new(double('inner object', :pid=>'foo', :new? =>true)) }
117
+ let(:list) { ds.elementList.build }
118
+ let!(:topic) { list.topicElement.build }
119
+
120
+ it "should have to_ary" do
121
+ list.to_ary.size.should == 1
122
+ list.to_ary.first.class.should == DemoList::List::TopicElement
123
+ end
124
+
125
+ it "should be able to be cleared" do
126
+ list.topicElement.build
127
+ list.topicElement.build
128
+ list.topicElement.build
129
+ list.size.should == 4
130
+ list.clear
131
+ list.size.should == 0
132
+ end
133
+ end
134
+
103
135
  describe "a list with content" do
104
136
  subject do
105
137
  subject = DemoList.new(double('inner object', :pid=>'foo', :new? =>true), 'descMetadata')
@@ -124,11 +156,13 @@ END
124
156
 
125
157
  subject
126
158
  end
127
- it "should have a subject" do
159
+ it "should have a subject" do
128
160
  subject.rdf_subject.to_s.should == "info:fedora/foo"
129
161
  end
162
+
163
+ let (:list) { subject.elementList.first }
164
+
130
165
  it "should have fields" do
131
- list = subject.elementList.first
132
166
  list.first.should == "http://library.ucsd.edu/ark:/20775/bbXXXXXXX6"
133
167
  list[1].should be_kind_of DemoList::List::TopicElement
134
168
  list[1].elementValue.should == ["Relations with Mexican Americans"]
@@ -137,13 +171,23 @@ END
137
171
  list[3].elementValue.should == ["20th century"]
138
172
  end
139
173
 
174
+ it "should have each" do
175
+ foo = []
176
+ list.each { |n| foo << n.class }
177
+ foo.should == [RDF::URI, DemoList::List::TopicElement, RDF::URI, DemoList::List::TemporalElement]
178
+ end
179
+
180
+ it "should have to_ary" do
181
+ ary = list.to_ary
182
+ ary.size.should == 4
183
+ ary[1].elementValue.should == ['Relations with Mexican Americans']
184
+ end
185
+
140
186
  it "should have size" do
141
- list = subject.elementList.first
142
187
  list.size.should == 4
143
188
  end
144
189
 
145
190
  it "should update fields" do
146
- list = subject.elementList.first
147
191
  list[3].elementValue = ["1900s"]
148
192
  expected_xml =<<END
149
193
  <rdf:RDF
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-fedora
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.4
4
+ version: 6.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Zumwalt
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-07-30 00:00:00.000000000 Z
13
+ date: 2013-08-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rsolr
@@ -343,6 +343,7 @@ files:
343
343
  - lib/active_fedora/railtie.rb
344
344
  - lib/active_fedora/rdf.rb
345
345
  - lib/active_fedora/rdf/nested_attributes.rb
346
+ - lib/active_fedora/rdf/node_config.rb
346
347
  - lib/active_fedora/rdf_datastream.rb
347
348
  - lib/active_fedora/rdf_list.rb
348
349
  - lib/active_fedora/rdf_node.rb
@@ -550,7 +551,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
550
551
  version: '0'
551
552
  requirements: []
552
553
  rubyforge_project:
553
- rubygems_version: 2.0.3
554
+ rubygems_version: 2.0.5
554
555
  signing_key:
555
556
  specification_version: 4
556
557
  summary: A convenience libary for manipulating documents in the Fedora Repository.