active-fedora 7.0.0.rc1 → 7.0.0.rc2
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 +4 -4
- data/lib/active_fedora/attributes.rb +15 -20
- data/lib/active_fedora/datastream.rb +9 -4
- data/lib/active_fedora/datastream_attribute.rb +33 -38
- data/lib/active_fedora/datastream_hash.rb +2 -2
- data/lib/active_fedora/datastreams.rb +43 -31
- data/lib/active_fedora/datastreams/nokogiri_datastreams.rb +146 -0
- data/lib/active_fedora/digital_object.rb +2 -2
- data/lib/active_fedora/indexing.rb +1 -1
- data/lib/active_fedora/nom_datastream.rb +7 -23
- data/lib/active_fedora/om_datastream.rb +3 -130
- data/lib/active_fedora/rdf_datastream.rb +4 -0
- data/lib/active_fedora/rdf_node.rb +1 -0
- data/lib/active_fedora/rdf_object.rb +1 -7
- data/lib/active_fedora/relation.rb +0 -29
- data/lib/active_fedora/relation/query_methods.rb +36 -0
- data/lib/active_fedora/simple_datastream.rb +1 -0
- data/lib/active_fedora/version.rb +1 -1
- data/spec/integration/base_spec.rb +2 -1
- data/spec/integration/om_datastream_spec.rb +2 -2
- data/spec/integration/scoped_query_spec.rb +13 -0
- data/spec/samples/hydra-mods_article_datastream.rb +1 -1
- data/spec/unit/datastream_spec.rb +0 -41
- data/spec/unit/datastreams_spec.rb +3 -3
- data/spec/unit/om_datastream_spec.rb +4 -1
- metadata +44 -43
@@ -4,10 +4,10 @@ module ActiveFedora
|
|
4
4
|
attr_accessor :original_class
|
5
5
|
|
6
6
|
module DatastreamBootstrap
|
7
|
-
def datastream_object_for dsid, ds_spec=nil
|
7
|
+
def datastream_object_for dsid, options={}, ds_spec=nil
|
8
8
|
# ds_spec is nil when called from Rubydora for existing datastreams, so it should not be autocreated
|
9
9
|
ds_spec ||= (original_class.ds_specs[dsid] || {}).merge(:autocreate=>false)
|
10
|
-
ds = ds_spec.fetch(:type, ActiveFedora::Datastream).new(self, dsid)
|
10
|
+
ds = ds_spec.fetch(:type, ActiveFedora::Datastream).new(self, dsid, options)
|
11
11
|
attributes = {}
|
12
12
|
attributes[:asOfDateTime] ||= asOfDateTime if self.respond_to? :asOfDateTime
|
13
13
|
attributes[:dsLabel] = ds_spec[:label] if ds_spec[:label].present?
|
@@ -2,6 +2,9 @@ require "nom"
|
|
2
2
|
|
3
3
|
module ActiveFedora
|
4
4
|
class NomDatastream < Datastream
|
5
|
+
|
6
|
+
include Datastreams::NokogiriDatastreams
|
7
|
+
|
5
8
|
def self.set_terminology(options = {}, &block)
|
6
9
|
@terminology_options = options || {}
|
7
10
|
@terminology = block
|
@@ -29,35 +32,16 @@ module ActiveFedora
|
|
29
32
|
ds
|
30
33
|
end
|
31
34
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
xml.nom!
|
37
|
-
xml
|
38
|
-
end
|
35
|
+
def self.decorate_ng_xml(xml)
|
36
|
+
xml.set_terminology terminology_options, &terminology
|
37
|
+
xml.nom!
|
38
|
+
xml
|
39
39
|
end
|
40
40
|
|
41
|
-
def ng_xml= ng_xml
|
42
|
-
@ng_xml = ng_xml
|
43
|
-
@ng_xml.set_terminology self.class.terminology_options, &self.class.terminology
|
44
|
-
content_will_change!
|
45
|
-
@ng_xml
|
46
|
-
end
|
47
|
-
|
48
41
|
def serialize!
|
49
42
|
self.content = @ng_xml.to_s if @ng_xml
|
50
43
|
end
|
51
44
|
|
52
|
-
def content
|
53
|
-
@content || super
|
54
|
-
end
|
55
|
-
|
56
|
-
def content=(content)
|
57
|
-
super
|
58
|
-
@ng_xml = nil
|
59
|
-
end
|
60
|
-
|
61
45
|
def to_solr
|
62
46
|
solr_doc = {}
|
63
47
|
|
@@ -12,7 +12,8 @@ module ActiveFedora
|
|
12
12
|
|
13
13
|
include OM::XML::Document
|
14
14
|
include OM::XML::TerminologyBasedSolrizer # this adds support for calling .to_solr
|
15
|
-
|
15
|
+
include Datastreams::NokogiriDatastreams
|
16
|
+
|
16
17
|
alias_method(:om_term_values, :term_values) unless method_defined?(:om_term_values)
|
17
18
|
alias_method(:om_update_values, :update_values) unless method_defined?(:om_update_values)
|
18
19
|
|
@@ -22,136 +23,12 @@ module ActiveFedora
|
|
22
23
|
super.merge(:controlGroup => 'M', :mimeType => 'text/xml')
|
23
24
|
end
|
24
25
|
|
25
|
-
# Create an instance of this class based on xml content
|
26
|
-
# @param [String, File, Nokogiri::XML::Node] xml the xml content to build from
|
27
|
-
# @param [ActiveFedora::OmDatastream] tmpl the Datastream object that you are building @default a new instance of this class
|
28
|
-
# Careful! If you call this from a constructor, be sure to provide something 'ie. self' as the @tmpl. Otherwise, you will get an infinite loop!
|
29
|
-
def self.from_xml(xml, tmpl=nil)
|
30
|
-
tmpl = self.new if tmpl.nil? ## This path is used only for unit testing (e.g. MarpaDCDatastream.from_xml(fixture("data.xml")) )
|
31
|
-
|
32
|
-
if !xml.present?
|
33
|
-
tmpl.ng_xml = self.xml_template
|
34
|
-
elsif xml.kind_of? Nokogiri::XML::Node || xml.kind_of?(Nokogiri::XML::Document)
|
35
|
-
tmpl.ng_xml = xml
|
36
|
-
else
|
37
|
-
tmpl.ng_xml = Nokogiri::XML::Document.parse(xml)
|
38
|
-
end
|
39
|
-
|
40
|
-
tmpl.ng_xml_doesnt_change!
|
41
|
-
|
42
|
-
return tmpl
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.xml_template
|
46
|
-
Nokogiri::XML::Document.parse("<xml/>")
|
47
|
-
end
|
48
|
-
|
49
|
-
def ng_xml
|
50
|
-
@ng_xml ||= begin
|
51
|
-
if new?
|
52
|
-
## Load up the template
|
53
|
-
self.class.xml_template
|
54
|
-
else
|
55
|
-
Nokogiri::XML::Document.parse(datastream_content)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def ng_xml=(new_xml)
|
61
|
-
# before we set ng_xml, we load the datastream so we know if the new value differs.
|
62
|
-
local_or_remote_content(true)
|
63
|
-
|
64
|
-
case new_xml
|
65
|
-
when Nokogiri::XML::Document
|
66
|
-
self.content=new_xml.to_xml
|
67
|
-
when Nokogiri::XML::Node
|
68
|
-
## Cast a fragment to a document
|
69
|
-
self.content=new_xml.to_s
|
70
|
-
when String
|
71
|
-
self.content=new_xml
|
72
|
-
else
|
73
|
-
raise TypeError, "You passed a #{new_xml.class} into the ng_xml of the #{self.dsid} datastream. OmDatastream.ng_xml= only accepts Nokogiri::XML::Document, Nokogiri::XML::Element, Nokogiri::XML::Node, or raw XML (String) as inputs."
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# don't want content eagerly loaded by proxy, so implementing methods that would be implemented by define_attribute_methods
|
78
|
-
def ng_xml_will_change!
|
79
|
-
changed_attributes['ng_xml'] = nil
|
80
|
-
end
|
81
|
-
|
82
|
-
def ng_xml_doesnt_change!
|
83
|
-
changed_attributes.delete('ng_xml')
|
84
|
-
end
|
85
|
-
|
86
|
-
# don't want content eagerly loaded by proxy, so implementing methods that would be implemented by define_attribute_methods
|
87
|
-
def ng_xml_changed?
|
88
|
-
changed_attributes.has_key? 'ng_xml'
|
89
|
-
end
|
90
|
-
|
91
26
|
# Indicates that this datastream has metadata content.
|
92
27
|
# @return true
|
93
28
|
def metadata?
|
94
29
|
true
|
95
30
|
end
|
96
31
|
|
97
|
-
def local_or_remote_content(ensure_fetch = true)
|
98
|
-
@content = to_xml if ng_xml_changed? || autocreate?
|
99
|
-
super
|
100
|
-
end
|
101
|
-
|
102
|
-
def autocreate?
|
103
|
-
changed_attributes.has_key? :profile
|
104
|
-
end
|
105
|
-
|
106
|
-
def datastream_content
|
107
|
-
@datastream_content ||= Nokogiri::XML(super).to_xml {|config| config.no_declaration}.strip
|
108
|
-
end
|
109
|
-
|
110
|
-
def content=(new_content)
|
111
|
-
if inline?
|
112
|
-
# inline datastreams may be transformed by fedora 3, so we test for equivalence instead of equality
|
113
|
-
if !EquivalentXml.equivalent?(datastream_content, new_content)
|
114
|
-
ng_xml_will_change!
|
115
|
-
@ng_xml = Nokogiri::XML::Document.parse(new_content)
|
116
|
-
super(@ng_xml.to_s)
|
117
|
-
end
|
118
|
-
else
|
119
|
-
if datastream_content != new_content
|
120
|
-
ng_xml_will_change!
|
121
|
-
@ng_xml = Nokogiri::XML::Document.parse(new_content)
|
122
|
-
super(@ng_xml.to_s)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def content_changed?
|
128
|
-
return false if !xml_loaded
|
129
|
-
super
|
130
|
-
end
|
131
|
-
|
132
|
-
def to_xml(xml = nil)
|
133
|
-
xml = self.ng_xml if xml.nil?
|
134
|
-
ng_xml = self.ng_xml
|
135
|
-
if ng_xml.respond_to?(:root) && ng_xml.root.nil? && self.class.respond_to?(:root_property_ref) && !self.class.root_property_ref.nil?
|
136
|
-
ng_xml = self.class.generate(self.class.root_property_ref, "")
|
137
|
-
if xml.root.nil?
|
138
|
-
xml = ng_xml
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
unless xml == ng_xml || ng_xml.root.nil?
|
143
|
-
if xml.kind_of?(Nokogiri::XML::Document)
|
144
|
-
xml.root.add_child(ng_xml.root)
|
145
|
-
elsif xml.kind_of?(Nokogiri::XML::Node)
|
146
|
-
xml.add_child(ng_xml.root)
|
147
|
-
else
|
148
|
-
raise "You can only pass instances of Nokogiri::XML::Node into this method. You passed in #{xml}"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
return xml.to_xml {|config| config.no_declaration}.strip
|
153
|
-
end
|
154
|
-
|
155
32
|
# ** Experimental **
|
156
33
|
#
|
157
34
|
# This method is called by ActiveFedora::Base.load_instance_from_solr
|
@@ -172,7 +49,7 @@ module ActiveFedora
|
|
172
49
|
# value returned by the +prefix+ method.
|
173
50
|
def to_solr(solr_doc = {})
|
174
51
|
prefix = self.prefix
|
175
|
-
super.each_with_object({}) { |(key, value), new| new[[prefix,key].join] = value }
|
52
|
+
solr_doc.merge super({}).each_with_object({}) { |(key, value), new| new[[prefix,key].join] = value }
|
176
53
|
end
|
177
54
|
|
178
55
|
|
@@ -422,9 +299,5 @@ module ActiveFedora
|
|
422
299
|
end
|
423
300
|
end
|
424
301
|
|
425
|
-
def xml_loaded
|
426
|
-
instance_variable_defined? :@ng_xml
|
427
|
-
end
|
428
|
-
|
429
302
|
end
|
430
303
|
end
|
@@ -7,13 +7,7 @@ module ActiveFedora
|
|
7
7
|
attr_reader :rdf_subject, :graph
|
8
8
|
end
|
9
9
|
|
10
|
-
def graph
|
11
|
-
@graph ||= RDF::Graph.new
|
12
|
-
@graph
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
def initialize(graph, subject=nil)
|
10
|
+
def initialize(graph = RDF::Graph.new, subject=nil)
|
17
11
|
subject ||= RDF::Node.new
|
18
12
|
@graph = graph
|
19
13
|
@rdf_subject = subject
|
@@ -50,35 +50,6 @@ module ActiveFedora
|
|
50
50
|
self
|
51
51
|
end
|
52
52
|
|
53
|
-
# Limits the returned records to those that match the provided search conditions
|
54
|
-
#
|
55
|
-
# @option [Hash] opts a hash of solr conditions
|
56
|
-
#
|
57
|
-
# @example
|
58
|
-
# Person.where(name_t: 'Mario', occupation_s: 'Plumber')
|
59
|
-
# => [#<Person @id="foo:123" @name='Mario'>, #<Person @id="foo:125" @name='Mario'>, ...]
|
60
|
-
def where(opts)
|
61
|
-
return self if opts.blank?
|
62
|
-
relation = clone
|
63
|
-
relation.where_values = opts
|
64
|
-
relation
|
65
|
-
end
|
66
|
-
|
67
|
-
# Order the returned records by the field and direction provided
|
68
|
-
#
|
69
|
-
# @option [Array<String>] args a list of fields and directions to sort by
|
70
|
-
#
|
71
|
-
# @example
|
72
|
-
# Person.where(occupation_s: 'Plumber').order('name_t desc', 'color_t asc')
|
73
|
-
# => [#<Person @id="foo:123" @name='Luigi'>, #<Person @id="foo:125" @name='Mario'>, ...]
|
74
|
-
def order(*args)
|
75
|
-
return self if args.blank?
|
76
|
-
|
77
|
-
relation = clone
|
78
|
-
relation.order_values += args.flatten
|
79
|
-
relation
|
80
|
-
end
|
81
|
-
|
82
53
|
def to_a
|
83
54
|
return @records if loaded?
|
84
55
|
args = @klass == ActiveFedora::Base ? {:cast=>true} : {}
|
@@ -37,6 +37,42 @@ module ActiveFedora
|
|
37
37
|
@values[:limit] = value
|
38
38
|
end
|
39
39
|
|
40
|
+
# Limits the returned records to those that match the provided search conditions
|
41
|
+
#
|
42
|
+
# @option [Hash] opts a hash of solr conditions
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# Person.where(name_t: 'Mario', occupation_s: 'Plumber')
|
46
|
+
# => [#<Person @id="foo:123" @name='Mario'>, #<Person @id="foo:125" @name='Mario'>, ...]
|
47
|
+
def where(values)
|
48
|
+
spawn.where!(values)
|
49
|
+
end
|
50
|
+
|
51
|
+
def where!(values)
|
52
|
+
if values.is_a?(String)
|
53
|
+
self.where_values = values
|
54
|
+
else
|
55
|
+
self.where_values = self.where_values.merge(values)
|
56
|
+
end
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Order the returned records by the field and direction provided
|
61
|
+
#
|
62
|
+
# @option [Array<String>] args a list of fields and directions to sort by
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# Person.where(occupation_s: 'Plumber').order('name_t desc', 'color_t asc')
|
66
|
+
# => [#<Person @id="foo:123" @name='Luigi'>, #<Person @id="foo:125" @name='Mario'>, ...]
|
67
|
+
def order(*args)
|
68
|
+
spawn.order!(args)
|
69
|
+
end
|
70
|
+
|
71
|
+
def order!(*args)
|
72
|
+
self.order_values += args.flatten
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
40
76
|
# Limits the number of returned records to the value specified
|
41
77
|
#
|
42
78
|
# @option [Integer] value the number of records to return
|
@@ -21,7 +21,8 @@ describe "A base object with metadata" do
|
|
21
21
|
obj.foo.should_not be_new
|
22
22
|
obj.foo.person.should == ['bob']
|
23
23
|
person_field = ActiveFedora::SolrService.solr_name('person', type: :string)
|
24
|
-
ActiveFedora::SolrService.query("{!raw f=id}#{@obj.pid}", :fl=>"id #{person_field}").first
|
24
|
+
solr_result = ActiveFedora::SolrService.query("{!raw f=id}#{@obj.pid}", :fl=>"id #{person_field}").first
|
25
|
+
expect(solr_result).to eq("id"=>@obj.pid, person_field =>['bob'])
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -7,7 +7,7 @@ describe ActiveFedora::OmDatastream do
|
|
7
7
|
before(:all) do
|
8
8
|
class ModsArticle3 < ActiveFedora::Base
|
9
9
|
# Uses the Hydra MODS Article profile for tracking most of the descriptive metadata
|
10
|
-
has_metadata
|
10
|
+
has_metadata "descMetadata", type: Hydra::ModsArticleDatastream, control_group: 'X', autocreate: true
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -56,7 +56,7 @@ describe ActiveFedora::OmDatastream do
|
|
56
56
|
before(:all) do
|
57
57
|
class ModsArticle2 < ActiveFedora::Base
|
58
58
|
# Uses the Hydra MODS Article profile for tracking most of the descriptive metadata
|
59
|
-
has_metadata
|
59
|
+
has_metadata "descMetadata", type: Hydra::ModsArticleDatastream, autocreate: true
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -81,6 +81,10 @@ describe "scoped queries" do
|
|
81
81
|
ModelIntegrationSpec::Basic.where(ActiveFedora::SolrService.solr_name('bar', type: :string) => 'Peanuts').order(ActiveFedora::SolrService.solr_name('foo', :sortable) + ' asc').limit(1).should == [test_instance2]
|
82
82
|
end
|
83
83
|
|
84
|
+
it "should chain where queries" do
|
85
|
+
ModelIntegrationSpec::Basic.where(ActiveFedora::SolrService.solr_name('bar', type: :string) => 'Peanuts').where(ActiveFedora::SolrService.solr_name('foo', type: :string) => 'bar').where_values.should == {ActiveFedora::SolrService.solr_name('bar', type: :string) => 'Peanuts', ActiveFedora::SolrService.solr_name('foo', type: :string) => 'bar'}
|
86
|
+
end
|
87
|
+
|
84
88
|
it "should chain count" do
|
85
89
|
ModelIntegrationSpec::Basic.where(ActiveFedora::SolrService.solr_name('bar', type: :string) => 'Peanuts').count.should == 2
|
86
90
|
end
|
@@ -90,6 +94,15 @@ describe "scoped queries" do
|
|
90
94
|
expect {relation.first}.not_to change {relation.to_a.size}
|
91
95
|
end
|
92
96
|
|
97
|
+
it "calling where should not affect the relation's ability to get all results later" do
|
98
|
+
relation = ModelIntegrationSpec::Basic.where(ActiveFedora::SolrService.solr_name('bar', type: :string) => 'Peanuts')
|
99
|
+
expect {relation.where(ActiveFedora::SolrService.solr_name('foo', type: :string) => 'bar')}.not_to change {relation.to_a.size}
|
100
|
+
end
|
101
|
+
|
102
|
+
it "calling order should not affect the original order of the relation later" do
|
103
|
+
relation = ModelIntegrationSpec::Basic.order(ActiveFedora::SolrService.solr_name('foo', :sortable) + ' asc')
|
104
|
+
expect {relation.order(ActiveFedora::SolrService.solr_name('foo', :sortable) + ' desc')}.not_to change {relation.to_a}
|
105
|
+
end
|
93
106
|
end
|
94
107
|
|
95
108
|
describe "when one of the objects in solr isn't in fedora" do
|
@@ -506,7 +506,7 @@ module Hydra
|
|
506
506
|
end
|
507
507
|
|
508
508
|
def to_solr(solr_doc=Hash.new)
|
509
|
-
super(solr_doc)
|
509
|
+
solr_doc = super(solr_doc)
|
510
510
|
|
511
511
|
::Solrizer::Extractor.insert_solr_field_value(solr_doc, Solrizer.default_field_mapper.solr_name('object_type', :facetable), "Article")
|
512
512
|
::Solrizer::Extractor.insert_solr_field_value(solr_doc, Solrizer.default_field_mapper.solr_name('mods_journal_title_info', :facetable), "Unknown") if solr_doc["mods_journal_title_info_facet"].nil?
|
@@ -19,47 +19,6 @@ describe ActiveFedora::Datastream do
|
|
19
19
|
@test_datastream.inspect.should match /#<ActiveFedora::Datastream @pid=\"\" @dsid=\"abcd\" @controlGroup=\"M\" changed=\"true\" @mimeType=\"\" >/
|
20
20
|
end
|
21
21
|
|
22
|
-
describe '#validate_content_present' do
|
23
|
-
before :each do
|
24
|
-
@test_datastream.content = nil
|
25
|
-
@test_datastream.dsLocation = nil
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should expect content on an Inline (X) datastream" do
|
29
|
-
@test_datastream.controlGroup = 'X'
|
30
|
-
@test_datastream.dsLocation = "http://example.com/test/content/abcd"
|
31
|
-
@test_datastream.validate_content_present.should be_false
|
32
|
-
@test_datastream.content = "<foo><xmlelement/></foo>"
|
33
|
-
@test_datastream.validate_content_present.should be_true
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should expect content on a Managed (M) datastream" do
|
37
|
-
@test_datastream.controlGroup = 'M'
|
38
|
-
@test_datastream.dsLocation = "http://example.com/test/content/abcd"
|
39
|
-
@test_datastream.validate_content_present.should be_false
|
40
|
-
@test_datastream.content = "<foo><xmlelement/></foo>"
|
41
|
-
@test_datastream.validate_content_present.should be_true
|
42
|
-
@test_datastream.should_not be_external
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should expect a dsLocation on an External (E) datastream" do
|
46
|
-
@test_datastream.controlGroup = 'E'
|
47
|
-
@test_datastream.content = "<foo><xmlelement/></foo>"
|
48
|
-
@test_datastream.validate_content_present.should be_false
|
49
|
-
@test_datastream.dsLocation = "http://example.com/test/content/abcd"
|
50
|
-
@test_datastream.validate_content_present.should be_true
|
51
|
-
@test_datastream.should be_external
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should expect a dsLocation on a Redirect (R) datastream" do
|
55
|
-
@test_datastream.controlGroup = 'R'
|
56
|
-
@test_datastream.content = "<foo><xmlelement/></foo>"
|
57
|
-
@test_datastream.validate_content_present.should be_false
|
58
|
-
@test_datastream.dsLocation = "http://example.com/test/content/abcd"
|
59
|
-
@test_datastream.validate_content_present.should be_true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
22
|
it "should have mimeType accessors" do
|
64
23
|
ds1 = ActiveFedora::Datastream.new
|
65
24
|
ds1.mimeType = "text/foo"
|