active-fedora 6.4.4 → 6.4.5

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.
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.