active-fedora 2.3.7 → 2.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rvmrc +1 -1
- data/Gemfile.lock +4 -2
- data/History.txt +7 -0
- data/active-fedora.gemspec +2 -1
- data/lib/active_fedora.rb +0 -1
- data/lib/active_fedora/base.rb +32 -15
- data/lib/active_fedora/datastream.rb +1 -0
- data/lib/active_fedora/nokogiri_datastream.rb +18 -17
- data/lib/active_fedora/solr_service.rb +7 -0
- data/lib/active_fedora/version.rb +1 -1
- data/lib/fedora/connection.rb +111 -75
- data/lib/fedora/repository.rb +28 -14
- data/spec/integration/repository_spec.rb +14 -9
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/connection_spec.rb +21 -21
- data/spec/unit/datastream_spec.rb +11 -0
- data/spec/unit/nokogiri_datastream_spec.rb +29 -3
- data/spec/unit/repository_spec.rb +2 -2
- data/spec/unit/solr_service_spec.rb +7 -0
- metadata +36 -20
data/.rvmrc
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
active-fedora (2.3.
|
5
|
-
activeresource
|
4
|
+
active-fedora (2.3.7)
|
5
|
+
activeresource (< 3.0.0)
|
6
6
|
equivalent-xml
|
7
7
|
facets
|
8
8
|
mediashelf-loggable
|
9
9
|
mime-types (>= 1.16)
|
10
10
|
multipart-post (= 1.1.2)
|
11
|
+
net-http-persistent
|
11
12
|
nokogiri
|
12
13
|
om (>= 1.0)
|
13
14
|
solr-ruby (>= 0.0.6)
|
@@ -38,6 +39,7 @@ GEM
|
|
38
39
|
mime-types (1.16)
|
39
40
|
mocha (0.9.12)
|
40
41
|
multipart-post (1.1.2)
|
42
|
+
net-http-persistent (2.1)
|
41
43
|
nokogiri (1.5.0)
|
42
44
|
om (1.4.0)
|
43
45
|
mediashelf-loggable
|
data/History.txt
CHANGED
data/active-fedora.gemspec
CHANGED
@@ -22,10 +22,11 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_dependency('nokogiri')
|
23
23
|
s.add_dependency('om', '>= 1.0')
|
24
24
|
s.add_dependency('solrizer', '>1.0.0')
|
25
|
-
s.add_dependency("activeresource")
|
25
|
+
s.add_dependency("activeresource", "<3.0.0")
|
26
26
|
s.add_dependency("mediashelf-loggable")
|
27
27
|
s.add_dependency("equivalent-xml")
|
28
28
|
s.add_dependency("facets")
|
29
|
+
s.add_dependency("net-http-persistent")
|
29
30
|
s.add_development_dependency("yard")
|
30
31
|
s.add_development_dependency("RedCloth") # for RDoc formatting
|
31
32
|
s.add_development_dependency("rake")
|
data/lib/active_fedora.rb
CHANGED
@@ -68,7 +68,6 @@ module ActiveFedora #:nodoc:
|
|
68
68
|
# 2. If it does not find a solr.yml and the fedora.yml contains a solr url, it will raise an configuration error
|
69
69
|
# 3. If it does not find a solr.yml and the fedora.yml does not contain a solr url, it will look in: +Rails.root+/config, +current working directory+/config, then the solr.yml shipped with gem
|
70
70
|
def self.init( options={} )
|
71
|
-
logger.level = Logger::ERROR if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
|
72
71
|
# Make config_options into a Hash if nil is passed in as the value
|
73
72
|
options = {} if options.nil?
|
74
73
|
|
data/lib/active_fedora/base.rb
CHANGED
@@ -4,6 +4,7 @@ require 'active_fedora/semantic_node'
|
|
4
4
|
require "solrizer"
|
5
5
|
require 'nokogiri'
|
6
6
|
require "loggable"
|
7
|
+
require 'benchmark'
|
7
8
|
|
8
9
|
SOLR_DOCUMENT_ID = "id" unless (defined?(SOLR_DOCUMENT_ID) && !SOLR_DOCUMENT_ID.nil?)
|
9
10
|
ENABLE_SOLR_UPDATES = true unless defined?(ENABLE_SOLR_UPDATES)
|
@@ -122,8 +123,12 @@ module ActiveFedora
|
|
122
123
|
# Refreshes the object's info from Fedora
|
123
124
|
# Note: Currently just registers any new datastreams that have appeared in fedora
|
124
125
|
def refresh
|
125
|
-
|
126
|
-
|
126
|
+
ms = 1000 * Benchmark.realtime do
|
127
|
+
inner_object.load_attributes_from_fedora
|
128
|
+
@datastreams = datastreams_in_fedora.merge(datastreams_in_memory)
|
129
|
+
end
|
130
|
+
logger.debug "refreshing #{pid} took #{ms} ms"
|
131
|
+
@datastreams
|
127
132
|
end
|
128
133
|
|
129
134
|
#Deletes a Base object, also deletes the info indexed in Solr, and
|
@@ -945,11 +950,17 @@ module ActiveFedora
|
|
945
950
|
def update_index
|
946
951
|
if defined?( Solrizer::Fedora::Solrizer )
|
947
952
|
#logger.info("Trying to solrize pid: #{pid}")
|
948
|
-
|
949
|
-
|
953
|
+
ms = 1000 * Benchmark.realtime do
|
954
|
+
solrizer = Solrizer::Fedora::Solrizer.new
|
955
|
+
solrizer.solrize( self )
|
956
|
+
end
|
957
|
+
logger.debug "solrize for #{pid} took #{ms} ms"
|
950
958
|
else
|
951
959
|
#logger.info("Trying to update solr for pid: #{pid}")
|
952
|
-
|
960
|
+
ms = 1000 * Benchmark.realtime do
|
961
|
+
SolrService.instance.conn.update(self.to_solr)
|
962
|
+
end
|
963
|
+
logger.debug "solr update for #{pid} took #{ms} ms"
|
953
964
|
end
|
954
965
|
end
|
955
966
|
|
@@ -1090,17 +1101,23 @@ module ActiveFedora
|
|
1090
1101
|
|
1091
1102
|
# Pushes the object and all of its new or dirty datastreams into Fedora
|
1092
1103
|
def update
|
1093
|
-
result =
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1104
|
+
result = nil
|
1105
|
+
ms = 1000 * Benchmark.realtime do
|
1106
|
+
result = Fedora::Repository.instance.save(@inner_object)
|
1107
|
+
end
|
1108
|
+
logger.debug "instance save for #{pid} took #{ms} ms"
|
1109
|
+
ms = 1000 * Benchmark.realtime do
|
1110
|
+
datastreams_in_memory.each do |k,ds|
|
1111
|
+
if ds.dirty? || ds.new_object?
|
1112
|
+
if ds.class.included_modules.include?(ActiveFedora::MetadataDatastreamHelper) || ds.instance_of?(ActiveFedora::RelsExtDatastream)
|
1113
|
+
@metadata_is_dirty = true
|
1114
|
+
end
|
1115
|
+
result = ds.save
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
refresh
|
1102
1119
|
end
|
1103
|
-
|
1120
|
+
logger.debug "datastream save for #{pid} took #{ms} ms"
|
1104
1121
|
return result
|
1105
1122
|
end
|
1106
1123
|
|
@@ -14,7 +14,8 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
14
14
|
alias_method(:om_term_values, :term_values) unless method_defined?(:om_term_values)
|
15
15
|
alias_method(:om_update_values, :update_values) unless method_defined?(:om_update_values)
|
16
16
|
|
17
|
-
attr_accessor :
|
17
|
+
attr_accessor :internal_solr_doc
|
18
|
+
attr_reader :ng_xml
|
18
19
|
|
19
20
|
#constructor, calls up to ActiveFedora::Datastream's constructor
|
20
21
|
def initialize(attrs=nil)
|
@@ -43,22 +44,22 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
43
44
|
Nokogiri::XML::Document.parse("<xml/>")
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
47
|
+
def ng_xml=(new_xml)
|
48
|
+
case new_xml
|
49
|
+
when Nokogiri::XML::Document, Nokogiri::XML::Element, Nokogiri::XML::Node
|
50
|
+
@ng_xml = new_xml
|
51
|
+
when String
|
52
|
+
@ng_xml = Nokogiri::XML::Document.parse(new_xml)
|
53
|
+
else
|
54
|
+
raise TypeError, "You passed a #{new_xml.class} into the ng_xml of the #{self.dsid} datastream. NokogiriDatastream.ng_xml= only accepts Nokogiri::XML::Document, Nokogiri::XML::Element, Nokogiri::XML::Node, or raw XML (String) as inputs."
|
55
|
+
end
|
56
|
+
self.dirty = true
|
57
|
+
end
|
58
|
+
|
59
|
+
def content=(content)
|
60
|
+
super
|
61
|
+
self.ng_xml = Nokogiri::XML::Document.parse(content)
|
62
|
+
end
|
62
63
|
|
63
64
|
|
64
65
|
def to_xml(xml = self.ng_xml)
|
@@ -65,6 +65,13 @@ module ActiveFedora
|
|
65
65
|
return uri.gsub(/(:)/, '\\:')
|
66
66
|
end
|
67
67
|
|
68
|
+
# Escapes these characters
|
69
|
+
# + - || ! ( ) { } [ ] ^ " ~ * ? : \
|
70
|
+
# See: http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Escaping%20Special%20Characters
|
71
|
+
def self.escape_characters_for_query(value)
|
72
|
+
value.gsub(/([\#\+\-\|\{\}\^\"\~\*\:\>\<\?\(\)\[\]\+\!\\])/) {|v| "\\#{v}"}
|
73
|
+
end
|
74
|
+
|
68
75
|
|
69
76
|
end #SolrService
|
70
77
|
class SolrNotInitialized < StandardError;end
|
data/lib/fedora/connection.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "base64"
|
2
2
|
gem 'multipart-post'
|
3
3
|
require 'net/http/post/multipart'
|
4
|
+
require 'net/http/persistent'
|
4
5
|
require 'cgi'
|
5
6
|
require "mime/types"
|
6
7
|
require 'net/http'
|
@@ -46,6 +47,9 @@ module Fedora
|
|
46
47
|
# 409 Conflict
|
47
48
|
class ResourceConflict < ClientError; end # :nodoc:
|
48
49
|
|
50
|
+
# 415 Unsupported Media Type
|
51
|
+
class UnsupportedMediaType < ClientError; end # :nodoc:
|
52
|
+
|
49
53
|
# 5xx Server Error
|
50
54
|
class ServerError < ConnectionError; end # :nodoc:
|
51
55
|
|
@@ -60,6 +64,23 @@ module Fedora
|
|
60
64
|
# This class is used by ActiveResource::Base to interface with REST
|
61
65
|
# services.
|
62
66
|
class Connection
|
67
|
+
|
68
|
+
CLASSES = [
|
69
|
+
Net::HTTP::Delete,
|
70
|
+
Net::HTTP::Get,
|
71
|
+
Net::HTTP::Head,
|
72
|
+
Net::HTTP::Post,
|
73
|
+
Net::HTTP::Put
|
74
|
+
].freeze
|
75
|
+
|
76
|
+
MIME_TYPES = {
|
77
|
+
:binary => "application/octet-stream",
|
78
|
+
:json => "application/json",
|
79
|
+
:xml => "text/xml",
|
80
|
+
:none => "text/plain"
|
81
|
+
}.freeze
|
82
|
+
|
83
|
+
|
63
84
|
attr_reader :site, :surrogate
|
64
85
|
attr_accessor :format
|
65
86
|
|
@@ -78,84 +99,102 @@ module Fedora
|
|
78
99
|
@surrogate=surrogate
|
79
100
|
end
|
80
101
|
|
102
|
+
##
|
103
|
+
# Perform an HTTP Delete, Head, Get, Post, or Put.
|
104
|
+
|
105
|
+
CLASSES.each do |clazz|
|
106
|
+
verb = clazz.to_s.split("::").last.downcase
|
107
|
+
|
108
|
+
define_method verb do |*args|
|
109
|
+
path = args[0]
|
110
|
+
params = args[1] || {}
|
111
|
+
|
112
|
+
response_for clazz, path, params
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
81
116
|
# Set URI for remote service.
|
82
117
|
def site=(site)
|
83
118
|
@site = site.is_a?(URI) ? site : URI.parse(site)
|
84
119
|
end
|
85
120
|
|
86
|
-
# Execute a GET request.
|
87
|
-
# Used to get (find) resources.
|
88
|
-
def get(path, headers = {})
|
89
|
-
format.decode(request(:get, path, build_request_headers(headers)).body)
|
90
|
-
end
|
91
|
-
|
92
|
-
# Execute a DELETE request (see HTTP protocol documentation if unfamiliar).
|
93
|
-
# Used to delete resources.
|
94
|
-
def delete(path, headers = {})
|
95
|
-
request(:delete, path, build_request_headers(headers))
|
96
|
-
end
|
97
121
|
|
122
|
+
private
|
98
123
|
|
124
|
+
# Makes request to remote service.
|
125
|
+
def response_for(clazz, path, params)
|
126
|
+
logger.debug "#{clazz} #{path}"
|
127
|
+
request = clazz.new path
|
128
|
+
request.body = params[:body]
|
99
129
|
|
100
|
-
|
101
|
-
request(:get, path, build_request_headers(headers))
|
102
|
-
end
|
103
|
-
def post(path, body='', headers={})
|
104
|
-
do_method(:post, path, body, headers)
|
105
|
-
end
|
106
|
-
def put( path, body='', headers={})
|
107
|
-
do_method(:put, path, body, headers)
|
130
|
+
handle_request request, params[:upload], params[:type], params[:headers] || {}
|
108
131
|
end
|
109
132
|
|
110
|
-
private
|
111
|
-
def do_method(method, path, body = '', headers = {})
|
112
|
-
meth_map={:put=>Net::HTTP::Put::Multipart, :post=>Net::HTTP::Post::Multipart}
|
113
|
-
raise "undefined method: #{method}" unless meth_map.has_key? method
|
114
|
-
headers = build_request_headers(headers)
|
115
|
-
if body.respond_to?(:read)
|
116
|
-
if body.respond_to?(:original_filename?)
|
117
|
-
filename = File.basename(body.original_filename)
|
118
|
-
io = UploadIO.new(body, mime_type,filename)
|
119
|
-
elsif body.path
|
120
|
-
filename = File.basename(body.path)
|
121
|
-
else
|
122
|
-
filename="NOFILE"
|
123
|
-
end
|
124
|
-
mime_types = MIME::Types.of(filename)
|
125
|
-
mime_type ||= mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
|
126
|
-
|
127
|
-
io = nil
|
128
|
-
if body.is_a?(File)
|
129
|
-
io = UploadIO.new(body.path,mime_type)
|
130
|
-
else
|
131
|
-
io =UploadIO.new(body, mime_type, filename)
|
132
|
-
end
|
133
133
|
|
134
|
-
|
135
|
-
|
134
|
+
def handle_request request, upload, type, headers
|
135
|
+
handle_uploads request, upload, type
|
136
|
+
handle_headers request, upload, type, headers
|
137
|
+
result = http.request self.site, request
|
138
|
+
handle_response(result)
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Handle chunked uploads.
|
143
|
+
#
|
144
|
+
# +request+: A Net::HTTP request Object.
|
145
|
+
# +upload+: A Hash with the following keys:
|
146
|
+
# +:file+: The file to be HTTP chunked uploaded.
|
147
|
+
# +:headers+: A Hash containing additional HTTP headers.
|
148
|
+
# +:type+: A Symbol with the mime_type.
|
149
|
+
|
150
|
+
def handle_uploads request, upload, type
|
151
|
+
return unless upload
|
152
|
+
io = nil
|
153
|
+
if upload[:file].is_a?(File)
|
154
|
+
io = File.open upload[:file].path
|
136
155
|
else
|
137
|
-
|
156
|
+
io = upload[:file]
|
138
157
|
end
|
158
|
+
|
159
|
+
request.body_stream = io
|
139
160
|
end
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
161
|
+
|
162
|
+
|
163
|
+
def handle_headers request, upload, type, headers
|
164
|
+
request.basic_auth(self.site.user, self.site.password) if self.site.user
|
165
|
+
|
166
|
+
request.add_field "Accept", mime_type(type)
|
167
|
+
request.add_field "Content-Type", mime_type(type) if requires_content_type? request
|
168
|
+
|
169
|
+
headers.merge! chunked_headers upload
|
170
|
+
headers.each do |header, value|
|
171
|
+
request[header] = value
|
145
172
|
end
|
146
|
-
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Setting of chunked upload headers.
|
177
|
+
#
|
178
|
+
# +upload+: A Hash with the following keys:
|
179
|
+
# +:file+: The file to be HTTP chunked uploaded.
|
180
|
+
|
181
|
+
def chunked_headers upload
|
182
|
+
return {} unless upload
|
147
183
|
|
184
|
+
chunked_headers = {
|
185
|
+
"Content-Type" => mime_type(:binary),
|
186
|
+
"Transfer-Encoding" => "chunked"
|
187
|
+
}.merge upload[:headers] || {}
|
148
188
|
end
|
149
189
|
|
150
|
-
|
151
|
-
|
152
|
-
result = http.send(method, path, *arguments)
|
153
|
-
handle_response(result)
|
190
|
+
def requires_content_type? request
|
191
|
+
[Net::HTTP::Post, Net::HTTP::Put].include? request.class
|
154
192
|
end
|
155
193
|
|
156
194
|
# Handles response and error codes from remote service.
|
157
195
|
def handle_response(response)
|
158
196
|
message = "Error from Fedora: #{response.body}"
|
197
|
+
logger.debug "Response: #{response.code}"
|
159
198
|
case response.code.to_i
|
160
199
|
when 301,302
|
161
200
|
raise(Redirection.new(response))
|
@@ -173,6 +212,8 @@ module Fedora
|
|
173
212
|
raise(MethodNotAllowed.new(response, message))
|
174
213
|
when 409
|
175
214
|
raise(ResourceConflict.new(response, message))
|
215
|
+
when 415
|
216
|
+
raise UnsupportedMediaType.new(response, message)
|
176
217
|
when 422
|
177
218
|
raise(ResourceInvalid.new(response, message))
|
178
219
|
when 423...500
|
@@ -184,35 +225,30 @@ module Fedora
|
|
184
225
|
end
|
185
226
|
end
|
186
227
|
|
228
|
+
def mime_type type
|
229
|
+
if type.kind_of? String
|
230
|
+
type
|
231
|
+
else
|
232
|
+
MIME_TYPES[type] || MIME_TYPES[:xml]
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
187
236
|
# Creates new Net::HTTP instance for communication with
|
188
237
|
# remote service and resources.
|
189
238
|
def http
|
190
|
-
http
|
239
|
+
return @http if @http
|
240
|
+
@http = Net::HTTP::Persistent.new#(@site)
|
191
241
|
if(@site.is_a?(URI::HTTPS))
|
192
|
-
http.use_ssl = true
|
193
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
242
|
+
@http.use_ssl = true
|
243
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
194
244
|
|
195
245
|
if (defined?(SSL_CLIENT_CERT_FILE) && !SSL_CLIENT_CERT_FILE.nil? && defined?(SSL_CLIENT_KEY_FILE) && !SSL_CLIENT_KEY_FILE.nil? && defined?(SSL_CLIENT_KEY_PASS) && !SSL_CLIENT_KEY_PASS.nil?)
|
196
|
-
http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
|
197
|
-
http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
|
246
|
+
@http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
|
247
|
+
@http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
|
198
248
|
end
|
199
249
|
end
|
200
|
-
http
|
250
|
+
@http
|
201
251
|
end
|
202
252
|
|
203
|
-
def default_header
|
204
|
-
@default_header ||= { 'Content-Type' => format.mime_type }
|
205
|
-
end
|
206
|
-
|
207
|
-
# Builds headers for request to remote service.
|
208
|
-
def build_request_headers(headers)
|
209
|
-
headers.merge!({"From"=>surrogate}) if @surrogate
|
210
|
-
authorization_header.update(default_header).update(headers)
|
211
|
-
end
|
212
|
-
|
213
|
-
# Sets authorization header; authentication information is pulled from credentials provided with site URI.
|
214
|
-
def authorization_header
|
215
|
-
(@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
|
216
|
-
end
|
217
253
|
end
|
218
254
|
end
|
data/lib/fedora/repository.rb
CHANGED
@@ -59,7 +59,7 @@ module Fedora
|
|
59
59
|
|
60
60
|
# Fetch the raw content of either a fedora object or datastream
|
61
61
|
def fetch_content(object_uri)
|
62
|
-
response = connection.
|
62
|
+
response = connection.get("#{url_for(object_uri)}?format=xml")
|
63
63
|
StringResponse.new(response.body, response.content_type)
|
64
64
|
end
|
65
65
|
|
@@ -95,7 +95,7 @@ module Fedora
|
|
95
95
|
params[:sessionToken] = options[:sessionToken] if options[:sessionToken]
|
96
96
|
includes = fields.inject("") { |s, f| s += "&#{f}=true"; s }
|
97
97
|
|
98
|
-
convert_xml(connection.get("#{fedora_url.path}/objects?#{params.to_fedora_query}#{includes}"))
|
98
|
+
convert_xml(XmlFormat.decode(connection.get("#{fedora_url.path}/objects?#{params.to_fedora_query}#{includes}").body))
|
99
99
|
end
|
100
100
|
|
101
101
|
# Retrieve an object from fedora and load it as an instance of the given model/class
|
@@ -103,10 +103,14 @@ module Fedora
|
|
103
103
|
# @param pid of the Fedora object to retrieve and deserialize
|
104
104
|
# @param klazz the Model whose deserialize method the object's FOXML will be passed into
|
105
105
|
def find_model(pid, klazz)
|
106
|
-
obj =
|
107
|
-
|
108
|
-
|
106
|
+
obj = nil
|
107
|
+
ms = 1000 * Benchmark.realtime do
|
108
|
+
obj = self.find_objects("pid=#{pid}").first
|
109
|
+
if obj.nil?
|
110
|
+
raise ActiveFedora::ObjectNotFoundError, "The repository does not have an object with pid #{pid}. The repository URL is #{self.base_url}"
|
111
|
+
end
|
109
112
|
end
|
113
|
+
logger.debug "loading #{pid} took #{ms} ms"
|
110
114
|
doc = Nokogiri::XML::Document.parse(obj.object_xml)
|
111
115
|
klazz.deserialize(doc)
|
112
116
|
end
|
@@ -132,7 +136,7 @@ module Fedora
|
|
132
136
|
case object
|
133
137
|
when Fedora::FedoraObject
|
134
138
|
pid = (object.pid ? object : 'new')
|
135
|
-
response = connection.post("#{url_for(pid)}?" + object.attributes.to_fedora_query, object.blob)
|
139
|
+
response = connection.post("#{url_for(pid)}?" + object.attributes.to_fedora_query, :body=>object.blob)
|
136
140
|
if response.code == '201'
|
137
141
|
object.pid = extract_pid(response)
|
138
142
|
object.new_object = false
|
@@ -142,10 +146,14 @@ module Fedora
|
|
142
146
|
end
|
143
147
|
when Fedora::Datastream
|
144
148
|
raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
object.blob
|
149
|
+
headers = {}
|
150
|
+
headers[:type] = object.attributes[:mimeType] if object.attributes[:mimeType]
|
151
|
+
if object.blob.respond_to? :read
|
152
|
+
headers[:upload] = {:file=>object.blob}
|
153
|
+
else
|
154
|
+
headers[:body]=object.blob
|
155
|
+
end
|
156
|
+
response = connection.post("#{url_for(object)}?" + object.attributes.to_fedora_query, headers)
|
149
157
|
if response.code == '201'
|
150
158
|
object.new_object = false
|
151
159
|
true
|
@@ -170,7 +178,13 @@ module Fedora
|
|
170
178
|
response.code == '200' || '307'
|
171
179
|
when Fedora::Datastream
|
172
180
|
raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
|
173
|
-
|
181
|
+
headers = {}
|
182
|
+
if object.blob.respond_to? :read
|
183
|
+
headers[:upload] = {:file=>object.blob}
|
184
|
+
else
|
185
|
+
headers[:body]=object.blob
|
186
|
+
end
|
187
|
+
response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query, headers)
|
174
188
|
response.code == '200' || '201'
|
175
189
|
return response.code
|
176
190
|
else
|
@@ -225,7 +239,7 @@ module Fedora
|
|
225
239
|
content_to_ingest = content_to_ingest.read
|
226
240
|
end
|
227
241
|
|
228
|
-
connection.post(url,content_to_ingest)
|
242
|
+
connection.post(url, :body=>content_to_ingest)
|
229
243
|
end
|
230
244
|
|
231
245
|
# Fetch the given object using custom method. This is used to fetch other aspects of a fedora object,
|
@@ -245,11 +259,11 @@ module Fedora
|
|
245
259
|
end
|
246
260
|
|
247
261
|
extra_params.delete(:format) if method == :export
|
248
|
-
connection.
|
262
|
+
connection.get("#{url_for(object)}#{path}?#{extra_params.to_fedora_query}").body
|
249
263
|
end
|
250
264
|
|
251
265
|
def describe_repository
|
252
|
-
result_body = connection.
|
266
|
+
result_body = connection.get("#{fedora_url.path}/describe?xml=true").body
|
253
267
|
XmlSimple.xml_in(result_body)
|
254
268
|
end
|
255
269
|
|
@@ -140,6 +140,8 @@ end
|
|
140
140
|
describe Fedora::Repository, "find_objects" do
|
141
141
|
before(:all) do
|
142
142
|
Fedora::Repository.register(ActiveFedora.fedora_config[:url])
|
143
|
+
@mock_response = mock("Response")
|
144
|
+
@mock_response.stubs(:body).returns(sample_response_xml)
|
143
145
|
end
|
144
146
|
|
145
147
|
def fields_to_s(fields)
|
@@ -156,31 +158,33 @@ describe Fedora::Repository, "find_objects" do
|
|
156
158
|
|
157
159
|
it "should include all fields by default" do
|
158
160
|
when_find_objects('label~Image*') { |conn|
|
159
|
-
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS))
|
161
|
+
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS)).returns(@mock_response)
|
160
162
|
}
|
161
163
|
end
|
162
164
|
|
163
165
|
it "should include all fields when :include => :all " do
|
164
166
|
when_find_objects('label~Image*', :include => :all) { |conn|
|
165
|
-
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS))
|
167
|
+
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS)).returns(@mock_response)
|
166
168
|
}
|
167
169
|
end
|
168
170
|
|
169
171
|
it "should fetch results with limit" do
|
170
172
|
when_find_objects('label~Image*', :limit => 10) { |conn|
|
171
|
-
conn.expects(:get).with('/fedora/objects?maxResults=10&query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS))
|
173
|
+
conn.expects(:get).with('/fedora/objects?maxResults=10&query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS)).returns(@mock_response)
|
172
174
|
}
|
173
175
|
end
|
174
176
|
|
175
177
|
it "should fetch results with some fields but not :pid" do
|
176
178
|
when_find_objects('label~Image*', :select => [:label, :mDate]) { |conn|
|
177
|
-
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate]))
|
179
|
+
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).returns(@mock_response)
|
180
|
+
|
178
181
|
}
|
179
182
|
end
|
180
183
|
|
181
184
|
it "should fetch results with some fields with :pid" do
|
182
185
|
when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
|
183
|
-
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate]))
|
186
|
+
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).returns(@mock_response)
|
187
|
+
|
184
188
|
}
|
185
189
|
end
|
186
190
|
|
@@ -203,7 +207,7 @@ describe Fedora::Repository, "find_objects" do
|
|
203
207
|
it "should convert xml response with 0 objectFields into array of FedoraObject" do
|
204
208
|
objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
|
205
209
|
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
|
206
|
-
returns(
|
210
|
+
returns(@mock_response)
|
207
211
|
}
|
208
212
|
|
209
213
|
objects.session_token.should == 'aToken'
|
@@ -213,7 +217,7 @@ describe Fedora::Repository, "find_objects" do
|
|
213
217
|
it "should return FedoraObjects with new_object set to false" do
|
214
218
|
objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
|
215
219
|
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
|
216
|
-
returns(
|
220
|
+
returns(@mock_response)
|
217
221
|
}
|
218
222
|
objects.each do |obj|
|
219
223
|
obj.should_not be_new_object
|
@@ -224,7 +228,7 @@ describe Fedora::Repository, "find_objects" do
|
|
224
228
|
it "should convert xml response with single objectFields into array of FedoraObject" do
|
225
229
|
objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
|
226
230
|
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
|
227
|
-
returns(
|
231
|
+
returns(@mock_response)
|
228
232
|
}
|
229
233
|
|
230
234
|
objects.session_token.should == 'aToken'
|
@@ -234,9 +238,10 @@ describe Fedora::Repository, "find_objects" do
|
|
234
238
|
end
|
235
239
|
|
236
240
|
it "should convert xml response 2 objectFields into array of FedoraObject" do
|
241
|
+
@mock_response.stubs(:body).returns(sample_response_xml(2))
|
237
242
|
objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
|
238
243
|
conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
|
239
|
-
returns(
|
244
|
+
returns(@mock_response)
|
240
245
|
}
|
241
246
|
|
242
247
|
objects.session_token.should == 'aToken'
|
data/spec/spec_helper.rb
CHANGED
@@ -14,6 +14,8 @@ end
|
|
14
14
|
ENV["RAILS_ENV"] ||= 'test'
|
15
15
|
RAILS_ENV = ENV["RAILS_ENV"]
|
16
16
|
|
17
|
+
logger.level = Logger::WARN if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
|
18
|
+
|
17
19
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
18
20
|
Dir[File.join(File.dirname(__FILE__)+'/../lib/')+'**/*.rb'].each{|x| require x unless x.match(/railtie.rb$/)}
|
19
21
|
$VERBOSE=nil
|
@@ -2,24 +2,24 @@ require File.join( File.dirname(__FILE__), "../spec_helper" )
|
|
2
2
|
|
3
3
|
require 'active_resource'
|
4
4
|
require 'fedora/repository'
|
5
|
-
|
6
|
-
describe Fedora::Connection do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
5
|
+
### Removed by Justin 2011-9-23
|
6
|
+
# describe Fedora::Connection do
|
7
|
+
# it "should be creatable w/ a surrogate id" do
|
8
|
+
# c = Fedora::Connection.new('http://127.0.0.1/fedora', 'fubar', 'bob')
|
9
|
+
# c.site.to_s.should == "http://127.0.0.1/fedora"
|
10
|
+
# c.format.should == 'fubar'
|
11
|
+
# c.surrogate.should == 'bob'
|
12
|
+
# end
|
13
|
+
# it "should set a from header if surrogate defined." do
|
14
|
+
# c = Fedora::Connection.new('http://127.0.0.1/fedora', ActiveResource::Formats[:xml], 'bob')
|
15
|
+
# h = Hash.new
|
16
|
+
# r= c.send(:build_request_headers,h)
|
17
|
+
# r['From'].should == 'bob'
|
18
|
+
# end
|
19
|
+
# it "should not set a from header if surrogate undefined." do
|
20
|
+
# c = Fedora::Connection.new('http://127.0.0.1/fedora' )
|
21
|
+
# h = Hash.new
|
22
|
+
# r= c.send(:build_request_headers,h)
|
23
|
+
# r['From'].should be_nil
|
24
|
+
# end
|
25
|
+
# end
|
@@ -60,6 +60,17 @@ describe ActiveFedora::Datastream do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
describe '.content=' do
|
64
|
+
it "should update the content and ng_xml, marking the datastream as dirty" do
|
65
|
+
sample_xml = "<foo><xmlelement/></foo>"
|
66
|
+
@test_datastream.should_not be_dirty
|
67
|
+
@test_datastream.blob.should_not be_equivalent_to(sample_xml)
|
68
|
+
@test_datastream.content = sample_xml
|
69
|
+
@test_datastream.should be_dirty
|
70
|
+
@test_datastream.blob.should be_equivalent_to(sample_xml)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
63
74
|
describe ".dirty?" do
|
64
75
|
it "should return the value of the @dirty attribute" do
|
65
76
|
@test_datastream.dirty.should equal(@test_datastream.dirty?)
|
@@ -10,7 +10,7 @@ describe ActiveFedora::NokogiriDatastream do
|
|
10
10
|
:empty_field => {:values => {}}
|
11
11
|
}
|
12
12
|
@sample_xml = XmlSimple.xml_in("<fields><coverage>coverage1</coverage><coverage>coverage2</coverage><creation_date>fake-date</creation_date><mydate>fake-date</mydate><publisher>publisher1</publisher></fields>")
|
13
|
-
|
13
|
+
@sample_raw_xml = "<foo><xmlelement/></foo>"
|
14
14
|
@solr_doc = {"id"=>"hydrange_article1","name_role_roleTerm_t"=>["creator","submitter","teacher"],"name_0_role_t"=>"\r\ncreator\r\nsubmitter\r\n","name_1_role_t"=>"\r\n teacher \r\n","name_0_role_0_roleTerm_t"=>"creator","name_0_role_1_roleTerm_t"=>"submitter","name_1_role_0_roleTerm_t"=>["teacher"]}
|
15
15
|
end
|
16
16
|
|
@@ -35,8 +35,8 @@ describe ActiveFedora::NokogiriDatastream do
|
|
35
35
|
test_ds1.ng_xml.to_xml.should == "<?xml version=\"1.0\"?>\n<xml>\n <foo/>\n</xml>\n"
|
36
36
|
end
|
37
37
|
it "should initialize from #xml_template if no xml is provided" do
|
38
|
-
ActiveFedora::NokogiriDatastream.expects(:xml_template).returns("fake template")
|
39
|
-
ActiveFedora::NokogiriDatastream.new.ng_xml.should
|
38
|
+
ActiveFedora::NokogiriDatastream.expects(:xml_template).returns("<fake template/>")
|
39
|
+
ActiveFedora::NokogiriDatastream.new.ng_xml.should be_equivalent_to("<fake template/>")
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -234,6 +234,32 @@ describe ActiveFedora::NokogiriDatastream do
|
|
234
234
|
end
|
235
235
|
end
|
236
236
|
|
237
|
+
describe '.content=' do
|
238
|
+
it "should update the content and ng_xml, marking the datastream as dirty" do
|
239
|
+
@test_ds.should_not be_dirty
|
240
|
+
@test_ds.blob.should_not be_equivalent_to(@sample_raw_xml)
|
241
|
+
@test_ds.ng_xml.to_xml.should_not be_equivalent_to(@sample_raw_xml)
|
242
|
+
@test_ds.content = @sample_raw_xml
|
243
|
+
@test_ds.should be_dirty
|
244
|
+
@test_ds.blob.should be_equivalent_to(@sample_raw_xml)
|
245
|
+
@test_ds.ng_xml.to_xml.should be_equivalent_to(@sample_raw_xml)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe 'ng_xml=' do
|
250
|
+
it "should parse raw xml for you" do
|
251
|
+
@test_ds.ng_xml.to_xml.should_not be_equivalent_to(@sample_raw_xml)
|
252
|
+
@test_ds.ng_xml = @sample_raw_xml
|
253
|
+
@test_ds.ng_xml.class.should == Nokogiri::XML::Document
|
254
|
+
@test_ds.ng_xml.to_xml.should be_equivalent_to(@sample_raw_xml)
|
255
|
+
end
|
256
|
+
it "should mark the datastream as dirty" do
|
257
|
+
@test_ds.should_not be_dirty
|
258
|
+
@test_ds.ng_xml = @sample_raw_xml
|
259
|
+
@test_ds.should be_dirty
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
237
263
|
describe '.to_xml' do
|
238
264
|
it "should provide .to_xml" do
|
239
265
|
@test_ds.should respond_to(:to_xml)
|
@@ -99,14 +99,14 @@ describe Fedora::Repository do
|
|
99
99
|
it "should post the provided xml or file to fedora" do
|
100
100
|
foxml = fixture("test_12.foxml.xml").read
|
101
101
|
connection = Fedora::Repository.instance.send(:connection)
|
102
|
-
connection.expects(:post).with("/fedora/objects/new"
|
102
|
+
connection.expects(:post).with("/fedora/objects/new",:body=>foxml)
|
103
103
|
Fedora::Repository.instance.ingest(foxml)
|
104
104
|
end
|
105
105
|
it "should accept a file as its input" do
|
106
106
|
foxml_file = fixture("test_12.foxml.xml")
|
107
107
|
foxml = fixture("test_12.foxml.xml").read
|
108
108
|
connection = Fedora::Repository.instance.send(:connection)
|
109
|
-
connection.expects(:post).with("/fedora/objects/new"
|
109
|
+
connection.expects(:post).with("/fedora/objects/new",:body=>foxml)
|
110
110
|
Fedora::Repository.instance.ingest(foxml_file)
|
111
111
|
end
|
112
112
|
end
|
@@ -84,4 +84,11 @@ describe ActiveFedora::SolrService do
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
+
describe "escape_characters_for_query" do
|
88
|
+
it "should escape the Solr special characters" do
|
89
|
+
test_val = '# + - || ! ( ) { } [ ] ^ " ~ * ? : \\'
|
90
|
+
expected_result = '\\# \\+ \\- \\|\\| \\! \\( \\) \\{ \\} \\[ \\] \\^ \\" \\~ \\* \\? \\: \\\\'
|
91
|
+
ActiveFedora::SolrService.escape_characters_for_query(test_val).should == expected_result
|
92
|
+
end
|
93
|
+
end
|
87
94
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active-fedora
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 2.3.
|
9
|
+
- 8
|
10
|
+
version: 2.3.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Zumwalt
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-09-
|
19
|
+
date: 2011-09-23 00:00:00 -05:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -133,12 +133,14 @@ dependencies:
|
|
133
133
|
requirement: &id008 !ruby/object:Gem::Requirement
|
134
134
|
none: false
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - <
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
hash:
|
138
|
+
hash: 7
|
139
139
|
segments:
|
140
|
+
- 3
|
140
141
|
- 0
|
141
|
-
|
142
|
+
- 0
|
143
|
+
version: 3.0.0
|
142
144
|
type: :runtime
|
143
145
|
version_requirements: *id008
|
144
146
|
- !ruby/object:Gem::Dependency
|
@@ -184,7 +186,7 @@ dependencies:
|
|
184
186
|
type: :runtime
|
185
187
|
version_requirements: *id011
|
186
188
|
- !ruby/object:Gem::Dependency
|
187
|
-
name:
|
189
|
+
name: net-http-persistent
|
188
190
|
prerelease: false
|
189
191
|
requirement: &id012 !ruby/object:Gem::Requirement
|
190
192
|
none: false
|
@@ -195,10 +197,10 @@ dependencies:
|
|
195
197
|
segments:
|
196
198
|
- 0
|
197
199
|
version: "0"
|
198
|
-
type: :
|
200
|
+
type: :runtime
|
199
201
|
version_requirements: *id012
|
200
202
|
- !ruby/object:Gem::Dependency
|
201
|
-
name:
|
203
|
+
name: yard
|
202
204
|
prerelease: false
|
203
205
|
requirement: &id013 !ruby/object:Gem::Requirement
|
204
206
|
none: false
|
@@ -212,7 +214,7 @@ dependencies:
|
|
212
214
|
type: :development
|
213
215
|
version_requirements: *id013
|
214
216
|
- !ruby/object:Gem::Dependency
|
215
|
-
name:
|
217
|
+
name: RedCloth
|
216
218
|
prerelease: false
|
217
219
|
requirement: &id014 !ruby/object:Gem::Requirement
|
218
220
|
none: false
|
@@ -226,7 +228,7 @@ dependencies:
|
|
226
228
|
type: :development
|
227
229
|
version_requirements: *id014
|
228
230
|
- !ruby/object:Gem::Dependency
|
229
|
-
name:
|
231
|
+
name: rake
|
230
232
|
prerelease: false
|
231
233
|
requirement: &id015 !ruby/object:Gem::Requirement
|
232
234
|
none: false
|
@@ -240,7 +242,7 @@ dependencies:
|
|
240
242
|
type: :development
|
241
243
|
version_requirements: *id015
|
242
244
|
- !ruby/object:Gem::Dependency
|
243
|
-
name:
|
245
|
+
name: rcov
|
244
246
|
prerelease: false
|
245
247
|
requirement: &id016 !ruby/object:Gem::Requirement
|
246
248
|
none: false
|
@@ -254,7 +256,7 @@ dependencies:
|
|
254
256
|
type: :development
|
255
257
|
version_requirements: *id016
|
256
258
|
- !ruby/object:Gem::Dependency
|
257
|
-
name:
|
259
|
+
name: solrizer-fedora
|
258
260
|
prerelease: false
|
259
261
|
requirement: &id017 !ruby/object:Gem::Requirement
|
260
262
|
none: false
|
@@ -268,9 +270,23 @@ dependencies:
|
|
268
270
|
type: :development
|
269
271
|
version_requirements: *id017
|
270
272
|
- !ruby/object:Gem::Dependency
|
271
|
-
name:
|
273
|
+
name: jettywrapper
|
272
274
|
prerelease: false
|
273
275
|
requirement: &id018 !ruby/object:Gem::Requirement
|
276
|
+
none: false
|
277
|
+
requirements:
|
278
|
+
- - ">="
|
279
|
+
- !ruby/object:Gem::Version
|
280
|
+
hash: 3
|
281
|
+
segments:
|
282
|
+
- 0
|
283
|
+
version: "0"
|
284
|
+
type: :development
|
285
|
+
version_requirements: *id018
|
286
|
+
- !ruby/object:Gem::Dependency
|
287
|
+
name: rspec
|
288
|
+
prerelease: false
|
289
|
+
requirement: &id019 !ruby/object:Gem::Requirement
|
274
290
|
none: false
|
275
291
|
requirements:
|
276
292
|
- - <
|
@@ -282,11 +298,11 @@ dependencies:
|
|
282
298
|
- 0
|
283
299
|
version: 2.0.0
|
284
300
|
type: :development
|
285
|
-
version_requirements: *
|
301
|
+
version_requirements: *id019
|
286
302
|
- !ruby/object:Gem::Dependency
|
287
303
|
name: mocha
|
288
304
|
prerelease: false
|
289
|
-
requirement: &
|
305
|
+
requirement: &id020 !ruby/object:Gem::Requirement
|
290
306
|
none: false
|
291
307
|
requirements:
|
292
308
|
- - ">="
|
@@ -298,11 +314,11 @@ dependencies:
|
|
298
314
|
- 8
|
299
315
|
version: 0.9.8
|
300
316
|
type: :development
|
301
|
-
version_requirements: *
|
317
|
+
version_requirements: *id020
|
302
318
|
- !ruby/object:Gem::Dependency
|
303
319
|
name: ruby-debug
|
304
320
|
prerelease: false
|
305
|
-
requirement: &
|
321
|
+
requirement: &id021 !ruby/object:Gem::Requirement
|
306
322
|
none: false
|
307
323
|
requirements:
|
308
324
|
- - ">="
|
@@ -312,7 +328,7 @@ dependencies:
|
|
312
328
|
- 0
|
313
329
|
version: "0"
|
314
330
|
type: :development
|
315
|
-
version_requirements: *
|
331
|
+
version_requirements: *id021
|
316
332
|
description: ActiveFedora provides for creating and managing objects in the Fedora Repository Architecture.
|
317
333
|
email:
|
318
334
|
- matt.zumwalt@yourmediashelf.com
|