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 +4 -4
- data/History.txt +129 -0
- data/lib/active_fedora.rb +3 -2
- data/lib/active_fedora/delegating.rb +2 -2
- data/lib/active_fedora/indexing.rb +1 -1
- data/lib/active_fedora/rdf.rb +1 -0
- data/lib/active_fedora/rdf/nested_attributes.rb +7 -13
- data/lib/active_fedora/rdf/node_config.rb +41 -0
- data/lib/active_fedora/rdf_datastream.rb +2 -2
- data/lib/active_fedora/rdf_list.rb +70 -23
- data/lib/active_fedora/rdf_node.rb +18 -43
- data/lib/active_fedora/rdf_node/term_proxy.rb +26 -10
- data/lib/active_fedora/rdf_object.rb +0 -5
- data/lib/active_fedora/version.rb +1 -1
- data/spec/integration/rdf_nested_attributes_spec.rb +32 -10
- data/spec/unit/active_fedora_spec.rb +6 -0
- data/spec/unit/rdf_datastream_spec.rb +18 -4
- data/spec/unit/rdf_list_nested_attributes_spec.rb +4 -1
- data/spec/unit/rdf_list_spec.rb +48 -4
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c3b9301740101d4e6c50bd6d5ce3f8e6bdf5d48
|
4
|
+
data.tar.gz: 84fed4e80fc0a7d1f5d2123836867f804427f797
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70b1bcb60f130c770e54866396de53f876d3529b0befce9bcfc180fe6b2540630c7b4df492057fe7dd4e2406b3cd35ecb9cd1a675af3f3ff0591be4716d752ba
|
7
|
+
data.tar.gz: d66329975f4374c0a46102235195760b1ac72ef7bddba684f9bbe6af16d2b2fc65cec3f7c526bed7870b0b38cb4a38569d480fce812b35b02e146306e5ec1543
|
data/History.txt
CHANGED
@@ -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]
|
data/lib/active_fedora.rb
CHANGED
@@ -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
|
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
|
-
# @
|
107
|
-
# @
|
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
|
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|
|
data/lib/active_fedora/rdf.rb
CHANGED
@@ -10,10 +10,10 @@ module ActiveFedora
|
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
|
-
UNASSIGNABLE_KEYS = %w(
|
13
|
+
UNASSIGNABLE_KEYS = %w(_destroy )
|
14
14
|
|
15
|
-
# @
|
16
|
-
# @
|
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)
|
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'].
|
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
|
-
|
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
|
145
|
-
behaviors = config
|
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)
|
24
|
-
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
|
-
|
32
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
108
|
-
graph.insert([subject, RDF.rest,
|
109
|
-
self.class.new(graph,
|
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 ?
|
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
|
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
|
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]
|
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
|
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
|
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
|
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
|
252
|
-
field = args.
|
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
|
-
|
256
|
-
|
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] =
|
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
|
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=
|
20
|
+
def build(attributes={})
|
21
21
|
node = mint_node(attributes)
|
22
|
-
parent.
|
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
|
-
|
34
|
-
|
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
|
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
|
85
|
+
if options.class_name
|
70
86
|
klass = class_from_rdf_type(v)
|
71
|
-
values << v if klass == ActiveFedora.class_from_string(options
|
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
|
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
|
@@ -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::
|
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
|
-
|
85
|
+
topicElement_attributes: [{elementValue:"Cosmology"}]
|
78
86
|
}]
|
79
87
|
},
|
80
88
|
'1' =>
|
81
89
|
{
|
82
90
|
elementList_attributes: [{
|
83
|
-
|
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.
|
114
|
-
subject.topic[1].elementList.first.
|
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 "
|
159
|
-
|
160
|
-
|
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(:
|
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
|
-
|
35
|
-
|
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
|
data/spec/unit/rdf_list_spec.rb
CHANGED
@@ -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
|
-
|
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
|
+
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-
|
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.
|
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.
|