active-fedora 7.0.0.rc1 → 7.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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?
@@ -25,7 +25,7 @@ module ActiveFedora
25
25
  solrize_profile(solr_doc)
26
26
  end
27
27
  datastreams.each_value do |ds|
28
- solr_doc = ds.to_solr(solr_doc)
28
+ solr_doc.merge! ds.to_solr()
29
29
  end
30
30
  solr_doc = solrize_relationships(solr_doc) unless opts[:model_only]
31
31
  solr_doc
@@ -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 ng_xml
33
- @ng_xml ||= begin
34
- xml = Nokogiri::XML content
35
- xml.set_terminology self.class.terminology_options, &self.class.terminology
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
@@ -25,6 +25,10 @@ module ActiveFedora
25
25
  end
26
26
  end
27
27
 
28
+ def freeze
29
+ @graph.freeze
30
+ end
31
+
28
32
  def metadata?
29
33
  true
30
34
  end
@@ -77,6 +77,7 @@ module ActiveFedora
77
77
  predicate = options.predicate
78
78
  values = Array(values)
79
79
 
80
+ raise "can't modify frozen #{self.class}" if graph.frozen?
80
81
  remove_existing_values(subject, predicate, values)
81
82
 
82
83
  values.each do |arg|
@@ -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
@@ -63,6 +63,7 @@ module ActiveFedora
63
63
  end
64
64
 
65
65
  def update_indexed_attributes(params={}, opts={})
66
+ raise "can't modify frozen #{self.class}" if frozen?
66
67
  # if the params are just keys, not an array, make then into an array.
67
68
  new_params = {}
68
69
  params.each do |key, val|
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "7.0.0.rc1"
2
+ VERSION = "7.0.0.rc2"
3
3
  end
@@ -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.should == {"id"=>@obj.pid, person_field =>['bob']}
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 :name => "descMetadata", :type => Hydra::ModsArticleDatastream, :control_group => 'X', :autocreate => true
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 :name => "descMetadata", :type => Hydra::ModsArticleDatastream, :autocreate => true
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"