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