active-fedora 7.0.0.pre2 → 7.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -7
  3. data/active-fedora.gemspec +2 -2
  4. data/lib/active_fedora/associations/builder/belongs_to.rb +1 -0
  5. data/lib/active_fedora/associations/has_many_association.rb +3 -2
  6. data/lib/active_fedora/core.rb +9 -0
  7. data/lib/active_fedora/datastream.rb +13 -0
  8. data/lib/active_fedora/datastream_attribute.rb +10 -9
  9. data/lib/active_fedora/datastream_hash.rb +7 -0
  10. data/lib/active_fedora/datastreams.rb +1 -1
  11. data/lib/active_fedora/indexing.rb +1 -2
  12. data/lib/active_fedora/om_datastream.rb +9 -1
  13. data/lib/active_fedora/persistence.rb +2 -5
  14. data/lib/active_fedora/querying.rb +5 -1
  15. data/lib/active_fedora/rdf/indexing.rb +18 -10
  16. data/lib/active_fedora/relation/finder_methods.rb +5 -5
  17. data/lib/active_fedora/rels_ext_datastream.rb +4 -24
  18. data/lib/active_fedora/semantic_node.rb +24 -9
  19. data/lib/active_fedora/solr_instance_loader.rb +1 -7
  20. data/lib/active_fedora/solr_service.rb +106 -98
  21. data/lib/active_fedora/version.rb +1 -1
  22. data/lib/generators/active_fedora/config/solr/templates/solr_conf/conf/schema.xml +5 -0
  23. data/lib/generators/active_fedora/config/solr/templates/solr_conf/conf/solrconfig.xml +51 -0
  24. data/spec/integration/has_many_associations_spec.rb +7 -0
  25. data/spec/integration/scoped_query_spec.rb +1 -1
  26. data/spec/integration/solr_service_spec.rb +6 -6
  27. data/spec/unit/base_extra_spec.rb +4 -4
  28. data/spec/unit/base_spec.rb +2 -2
  29. data/spec/unit/core_spec.rb +77 -0
  30. data/spec/unit/ntriples_datastream_spec.rb +4 -4
  31. data/spec/unit/om_datastream_spec.rb +40 -4
  32. data/spec/unit/query_spec.rb +19 -19
  33. data/spec/unit/rels_ext_datastream_spec.rb +3 -2
  34. data/spec/unit/solr_config_options_spec.rb +1 -4
  35. data/spec/unit/solr_service_spec.rb +7 -1
  36. metadata +10 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4016c59a3c3f1110b5cb6a9eb82dc1ecc374e09
4
- data.tar.gz: 17257166e62dd7dbdefbcdf8acc0913497a25d4b
3
+ metadata.gz: 326d249cd4fae27ff020852f7f76213ebc79f29f
4
+ data.tar.gz: 4a71080c33394383361845919afe864472eedf27
5
5
  SHA512:
6
- metadata.gz: dc945c04a877bc385439846091a494cf098f229ee0a869106a8ad82d35975adec0eedb103e2a489f69c5b8b7cd03015f77525745279197856fafe37cfe9c193f
7
- data.tar.gz: d7e48d90b96306a956bfac1731c6180d29b3e4cb0ff913ef86826fe150d97a4d42e207a5d0b08f5a5d9c60beb52e2d12baf858e7d3ea3bbe7546d02fd7c69c40
6
+ metadata.gz: 0191dcb8e84050abc5869f1ec0d5003195774421929e1ddb8e7f31d461eca505458af240f3ca9f4eefee323c62d819bf34b8cf9a12fdbf1c118ce4ab5c9040c2
7
+ data.tar.gz: 21202208679bb2bd1982377c60a597ab07bc70923d68bedeb31e45476e1b984b530e80e6d44357a2b567ffb83badc7a04bbd3f1a90079aa3be4ea5e340ac6fdb
@@ -4,11 +4,6 @@ rvm:
4
4
  - 2.0.0
5
5
  - 1.9.3
6
6
 
7
- matrix:
8
- allow_failures:
9
- - rvm: 2.1.0
10
-
11
-
12
7
  gemfile:
13
8
  - gemfiles/rails3.gemfile
14
9
  - gemfiles/rails4.gemfile
@@ -16,8 +11,6 @@ gemfile:
16
11
  notifications:
17
12
  irc: "irc.freenode.org#projecthydra"
18
13
 
19
- before_install:
20
- - gem install bundler
21
14
  env:
22
15
  global:
23
16
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
@@ -14,12 +14,12 @@ Gem::Specification.new do |s|
14
14
  s.license = "APACHE2"
15
15
  s.required_ruby_version = '>= 1.9.3'
16
16
 
17
- s.add_dependency('rsolr')
17
+ s.add_dependency('rsolr', "~> 1.0.10.pre1")
18
18
  s.add_dependency('om', '~> 3.0.0')
19
19
  s.add_dependency('nom-xml', '>=0.5.1')
20
20
  s.add_dependency("activesupport", '>= 3.0.0')
21
21
  s.add_dependency("mediashelf-loggable")
22
- s.add_dependency("rubydora", '~>1.7.0.pre1')
22
+ s.add_dependency("rubydora", '~>1.7.0')
23
23
  s.add_dependency("rdf")
24
24
  s.add_dependency("rdf-rdfxml", '~>1.1.0')
25
25
  s.add_dependency("deprecation")
@@ -93,6 +93,7 @@ module ActiveFedora::Associations::Builder
93
93
  writer_name = "#{name}_id"
94
94
  model.find_or_create_defined_attribute(writer_name, 'RELS-EXT', {})
95
95
  mixin.redefine_method("#{writer_name}=") do |id|
96
+ raise "can't modify frozen #{self.class}" if self.frozen?
96
97
  association(name).id_writer(id)
97
98
  end
98
99
  end
@@ -55,7 +55,6 @@ module ActiveFedora
55
55
  inverse = reflection.inverse_of.name
56
56
  records.each do |record|
57
57
  if record.persisted?
58
- record.reload
59
58
  assoc = record.association(inverse)
60
59
  if assoc.reflection.collection?
61
60
  # Remove from a has_and_belongs_to_many
@@ -64,7 +63,9 @@ module ActiveFedora
64
63
  # Remove from a belongs_to
65
64
  record.association(inverse).id_writer(nil)
66
65
  end
67
- record.save!
66
+ # Check to see if the object still exists (may be already deleted).
67
+ # In Rails, they do this with an update_all to avoid callbacks and validations, we may need the same.
68
+ record.save! if record.class.exists?(record.pid)
68
69
  end
69
70
  end
70
71
  end
@@ -85,6 +85,15 @@ module ActiveFedora
85
85
  new_object if new_object.save
86
86
  end
87
87
 
88
+ def freeze
89
+ datastreams.freeze
90
+ self
91
+ end
92
+
93
+ def frozen?
94
+ datastreams.frozen?
95
+ end
96
+
88
97
  def pretty_pid
89
98
  if self.pid == UnsavedDigitalObject::PLACEHOLDER
90
99
  nil
@@ -2,6 +2,7 @@ module ActiveFedora
2
2
 
3
3
  #This class represents a Fedora datastream
4
4
  class Datastream < Rubydora::Datastream
5
+ extend Deprecation
5
6
  attr_writer :digital_object
6
7
  attr_accessor :last_modified
7
8
 
@@ -73,6 +74,18 @@ module ActiveFedora
73
74
  def to_solr(solr_doc = Hash.new)
74
75
  solr_doc
75
76
  end
77
+
78
+ protected
79
+ # The string to prefix all solr fields with. Override this method if you want
80
+ # a prefix other than the default
81
+ def prefix
82
+ raise RuntimeError, "to_solr requires the dsid to be set" unless dsid
83
+ Deprecation.warn ActiveFedora::Datastream, "In active-fedora 8 the solr fields created by #{self.class} will be prefixed with \"#{dsid.underscore}__\". If you want to maintain the existing behavior, you must override #{self.class}.#prefix to return an empty string"
84
+ # In ActiveFedora 8 return this:
85
+ #"#{dsid.underscore}__"
86
+ ""
87
+ end
88
+
76
89
  end
77
90
 
78
91
  class DatastreamConcurrencyException < Exception # :nodoc:
@@ -2,12 +2,12 @@ module ActiveFedora
2
2
  # Represents the mapping between a model attribute and a field in a datastream
3
3
  class DatastreamAttribute
4
4
 
5
- attr_accessor :dsid, :field, :klass, :at, :reader, :writer, :multiple
5
+ attr_accessor :dsid, :field, :datastream_class, :at, :reader, :writer, :multiple
6
6
 
7
- def initialize(field, dsid, klass, args={})
7
+ def initialize(field, dsid, datastream_class, args={})
8
8
  self.field = field
9
9
  self.dsid = dsid
10
- self.klass = klass
10
+ self.datastream_class = datastream_class
11
11
  self.multiple = args[:multiple].nil? ? false : args[:multiple]
12
12
  self.at = args[:at]
13
13
 
@@ -17,18 +17,19 @@ module ActiveFedora
17
17
 
18
18
  # Gives the primary solr name for a column. If there is more than one indexer on the field definition, it gives the first
19
19
  def primary_solr_name
20
- if klass.respond_to?(:primary_solr_name)
21
- klass.primary_solr_name(dsid, field)
20
+ @datastream ||= datastream_class.new(nil, dsid)
21
+ if @datastream.respond_to?(:primary_solr_name)
22
+ @datastream.primary_solr_name(field)
22
23
  else
23
- raise IllegalOperation, "the class '#{klass}' doesn't respond to 'primary_solr_name'"
24
+ raise IllegalOperation, "the datastream '#{datastream_class}' doesn't respond to 'primary_solr_name'"
24
25
  end
25
26
  end
26
27
 
27
28
  def type
28
- if klass.respond_to?(:type)
29
- klass.type(field)
29
+ if datastream_class.respond_to?(:type)
30
+ datastream_class.type(field)
30
31
  else
31
- raise IllegalOperation, "the class '#{klass}' doesn't respond to 'type'"
32
+ raise IllegalOperation, "the datastream '#{datastream_class}' doesn't respond to 'type'"
32
33
  end
33
34
  end
34
35
 
@@ -18,5 +18,12 @@ module ActiveFedora
18
18
  @obj.inner_object.datastreams[key]=val# unless @obj.inner_object.new?
19
19
  super
20
20
  end
21
+
22
+ def freeze
23
+ each do |k, v|
24
+ v.freeze
25
+ end
26
+ super
27
+ end
21
28
  end
22
29
  end
@@ -175,7 +175,7 @@ module ActiveFedora
175
175
 
176
176
  module ClassMethods
177
177
  # @param [String] dsid the datastream id
178
- # @returns [Class] the class of the datastream
178
+ # @return [Class] the class of the datastream
179
179
  def datastream_class_for_name(dsid)
180
180
  ds_specs[dsid] ? ds_specs[dsid].fetch(:type, ActiveFedora::Datastream) : ActiveFedora::Datastream
181
181
  end
@@ -69,8 +69,7 @@ module ActiveFedora
69
69
  solrizer = Solrizer::Fedora::Solrizer.new
70
70
  solrizer.solrize( self )
71
71
  else
72
- SolrService.add(self.to_solr)
73
- SolrService.commit
72
+ SolrService.add(self.to_solr, softCommit: true)
74
73
  end
75
74
  end
76
75
 
@@ -17,7 +17,7 @@ module ActiveFedora
17
17
  alias_method(:om_update_values, :update_values) unless method_defined?(:om_update_values)
18
18
 
19
19
  attr_accessor :internal_solr_doc
20
-
20
+
21
21
  def self.default_attributes
22
22
  super.merge(:controlGroup => 'M', :mimeType => 'text/xml')
23
23
  end
@@ -168,6 +168,13 @@ module ActiveFedora
168
168
  @internal_solr_doc = solr_doc
169
169
  end
170
170
 
171
+ # Return a hash suitable for indexing in solr. Every field name is prefixed with the
172
+ # value returned by the +prefix+ method.
173
+ def to_solr(solr_doc = {})
174
+ prefix = self.prefix
175
+ super.each_with_object({}) { |(key, value), new| new[[prefix,key].join] = value }
176
+ end
177
+
171
178
 
172
179
  # ** Experimental **
173
180
  # This method is called by +get_values+ if this datastream has been initialized by calling from_solr method via
@@ -394,6 +401,7 @@ module ActiveFedora
394
401
  # ds.update_values( {[{":person"=>"0"}, "role", "text"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, [{:person=>1}, :family_name]=>"Andronicus", [{"person"=>"1"},:given_name]=>["Titus"],[{:person=>1},:role,:text]=>["otherrole1","otherrole2"] } )
395
402
  # => {"person_0_role_text"=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, "person_1_role_text"=>{"0"=>"otherrole1", "1"=>"otherrole2"}}
396
403
  def update_values(params={})
404
+ raise "can't modify frozen #{self.class}" if frozen?
397
405
  if @internal_solr_doc
398
406
  raise "No update performed, this object was initialized via Solr instead of Fedora and is therefore read-only. Please utilize ActiveFedora::Base.find to first load object via Fedora instead."
399
407
  else
@@ -20,7 +20,7 @@ module ActiveFedora
20
20
 
21
21
  ## Required by associations
22
22
  def new_record?
23
- inner_object.new?
23
+ inner_object.new_record?
24
24
  end
25
25
 
26
26
  def persisted?
@@ -73,8 +73,6 @@ module ActiveFedora
73
73
  end
74
74
  end
75
75
 
76
-
77
- #Fedora::Repository.instance.delete(@inner_object)
78
76
  pid = self.pid ## cache so it's still available after delete
79
77
  begin
80
78
  @inner_object.delete
@@ -83,8 +81,7 @@ module ActiveFedora
83
81
  end
84
82
  if ENABLE_SOLR_UPDATES
85
83
  solr = ActiveFedora::SolrService.instance.conn
86
- solr.delete_by_id(pid)
87
- solr.commit
84
+ solr.delete_by_id(pid, params: {'softCommit' => true})
88
85
  end
89
86
  @destroyed = true
90
87
  freeze
@@ -1,5 +1,8 @@
1
1
  module ActiveFedora
2
2
  module Querying
3
+ extend Deprecation
4
+ self.deprecation_horizon = 'active-fedora version 8.0.0'
5
+
3
6
  delegate :find, :first, :exists?, :where, :limit, :order, :delete_all,
4
7
  :destroy_all, :count, :last, :find_with_conditions, :find_in_batches, :find_each, :to=>:all
5
8
 
@@ -13,7 +16,8 @@ module ActiveFedora
13
16
  end
14
17
 
15
18
  def quote_for_solr(value)
16
- '"' + value.gsub(/(:)/, '\\:').gsub(/(\/)/, '\\/').gsub(/"/, '\\"') + '"'
19
+ RSolr.escape(value)
17
20
  end
21
+ deprecation_deprecate :quote_for_solr
18
22
  end
19
23
  end
@@ -1,10 +1,17 @@
1
1
  module ActiveFedora
2
2
  module Rdf
3
3
  module Indexing
4
+ extend Deprecation
4
5
  extend ActiveSupport::Concern
5
6
 
7
+ # In active_fedora 8, we can get the prefix part from Datastream.prefix
8
+ def apply_prefix(name)
9
+ "#{dsid.underscore}__#{name}"
10
+ end
11
+
6
12
  def prefix(name)
7
- self.class.prefix(dsid, name)
13
+ Deprecation.warn Indexing, "prefix is deprecated. Use apply_prefix instead. In active-fedora 8, the prefix method will just return the prefix to be applied, and will not do the applying. This will enable conformity between OmDatastream and RdfDatastream"
14
+ apply_prefix(name)
8
15
  end
9
16
 
10
17
  def to_solr(solr_doc = Hash.new) # :nodoc:
@@ -12,26 +19,27 @@ module ActiveFedora
12
19
  values = get_values(rdf_subject, field_key)
13
20
  Array(values).each do |val|
14
21
  val = val.to_s if val.kind_of? RDF::URI
15
- Solrizer.insert_field(solr_doc, prefix(field_key), val, *field_info[:behaviors])
22
+ Solrizer.insert_field(solr_doc, apply_prefix(field_key), val, *field_info[:behaviors])
16
23
  end
17
24
  end
18
25
  solr_doc
19
26
  end
20
27
 
28
+ # Gives the primary solr name for a column. If there is more than one indexer on the field definition, it gives the first
29
+ def primary_solr_name(field)
30
+ config = self.class.config_for_term_or_uri(field)
31
+ if behaviors = config.behaviors
32
+ ActiveFedora::SolrService.solr_name(apply_prefix(field), behaviors.first, type: config.type)
33
+ end
34
+ end
35
+
21
36
 
22
37
  module ClassMethods
23
38
  def prefix(dsid, name)
39
+ Deprecation.warn Indexing, "prefix is deprecated and will be removed in active-fedora 8.0.0.", caller
24
40
  "#{dsid.underscore}__#{name}".to_sym
25
41
  end
26
42
 
27
- # Gives the primary solr name for a column. If there is more than one indexer on the field definition, it gives the first
28
- def primary_solr_name(dsid, field)
29
- config = config_for_term_or_uri(field)
30
- if behaviors = config.behaviors
31
- ActiveFedora::SolrService.solr_name(prefix(dsid, field), behaviors.first, type: config.type)
32
- end
33
- end
34
-
35
43
  # Gives the datatype for a column.
36
44
  def type(field)
37
45
  config_for_term_or_uri(field).type
@@ -151,8 +151,9 @@ module ActiveFedora
151
151
  if where_values.empty?
152
152
  load_from_fedora(pid, cast)
153
153
  else
154
- query = ActiveFedora::SolrService.construct_query_for_rel(where_values)
155
- query += " AND _query_:\"{!raw f=id}#{pid}\""
154
+ query = [ActiveFedora::SolrService.construct_query_for_rel(where_values),
155
+ ActiveFedora::SolrService.raw_query(SOLR_DOCUMENT_ID, pid)].
156
+ join(" AND ".freeze)
156
157
  to_enum(:find_each, query, {}).to_a.first
157
158
  end
158
159
  end
@@ -218,11 +219,10 @@ module ActiveFedora
218
219
  if value.empty?
219
220
  "-#{key}:['' TO *]"
220
221
  elsif value.is_a? Array
221
- value.map { |val| "#{key}:#{@klass.quote_for_solr(val)}" }
222
+ value.map { |val| "#{key}:#{RSolr.escape(val)}" }
222
223
  else
223
224
  key = SOLR_DOCUMENT_ID if (key === :id || key === :pid)
224
- escaped_value = @klass.quote_for_solr(value)
225
- key.to_s.eql?(SOLR_DOCUMENT_ID) ? "#{key}:#{escaped_value}" : "#{key}:#{escaped_value}"
225
+ "#{key}:#{RSolr.escape(value)}"
226
226
  end
227
227
  end
228
228
  end
@@ -13,7 +13,7 @@ module ActiveFedora
13
13
  end
14
14
 
15
15
  def changed?
16
- relationships_are_dirty? or super
16
+ model.relationships_are_dirty? or super
17
17
  end
18
18
 
19
19
  def metadata?
@@ -21,22 +21,10 @@ module ActiveFedora
21
21
  end
22
22
 
23
23
  def serialize!
24
- self.content = to_rels_ext() if relationships_are_dirty?
25
- model.relationships_are_dirty = false
24
+ self.content = to_rels_ext() if model.relationships_are_dirty?
25
+ model.relationships_are_not_dirty!
26
26
  end
27
27
 
28
- def relationships_are_dirty?
29
- model.relationships_are_dirty if model
30
- end
31
-
32
- def relationships_are_dirty!
33
- model.relationships_are_dirty = true
34
- end
35
-
36
- def relationships_are_not_dirty!
37
- model.relationships_are_dirty = false
38
- end
39
-
40
28
  # Populate a RelsExtDatastream object based on the "datastream" content
41
29
  # Assumes that the datastream contains RDF XML from a Fedora RELS-EXT datastream
42
30
  # @param [String] xml the "rdf" node
@@ -46,15 +34,7 @@ module ActiveFedora
46
34
  ### maybe put the template here?
47
35
  else
48
36
  ensure_predicates_exist!(xml)
49
- RDF::RDFXML::Reader.new(xml) do |reader|
50
- reader.each_statement do |statement|
51
- literal = statement.object.kind_of?(RDF::Literal)
52
- object = literal ? statement.object.value : statement.object.to_str
53
- tmpl.model.add_relationship(statement.predicate, object, literal)
54
- end
55
- end
56
- tmpl.relationships_are_not_dirty!
57
- tmpl.changed_attributes.clear
37
+ tmpl.model.relationships = xml
58
38
  tmpl
59
39
  end
60
40
  end
@@ -19,12 +19,27 @@ module ActiveFedora
19
19
  load_relationships if !relationships_loaded
20
20
  @object_relations ||= RelationshipGraph.new
21
21
  end
22
-
23
- def relationships_are_dirty
22
+
23
+ def relationships_are_dirty?
24
24
  object_relations.dirty
25
25
  end
26
- def relationships_are_dirty=(val)
27
- object_relations.dirty = val
26
+ alias relationships_are_dirty relationships_are_dirty?
27
+
28
+ def relationships_are_not_dirty!
29
+ object_relations.dirty = false
30
+ end
31
+
32
+ def relationships=(xml)
33
+ RDF::RDFXML::Reader.new(xml) do |reader|
34
+ reader.each_statement do |statement|
35
+ literal = statement.object.kind_of?(RDF::Literal)
36
+ object = literal ? statement.object.value : statement.object.to_str
37
+ object_relations.add(statement.predicate, object, literal)
38
+ end
39
+ end
40
+ # Adding the relationships to the graph causes the graph to be marked as dirty,
41
+ # so now we assert that the graph is in sync
42
+ relationships_are_not_dirty!
28
43
  end
29
44
 
30
45
  # Add a relationship to the Object.
@@ -80,7 +95,7 @@ module ActiveFedora
80
95
  # @param obj Either a string URI or an object that responds to .pid
81
96
  def remove_relationship(predicate, obj, literal=false)
82
97
  object_relations.delete(predicate, obj)
83
- self.relationships_are_dirty = true
98
+ object_relations.dirty = true
84
99
  rels_ext.content_will_change!
85
100
  end
86
101
 
@@ -111,14 +126,14 @@ module ActiveFedora
111
126
  end
112
127
  end
113
128
 
114
- # @returns [String] the internal fedora URI
129
+ # @return [String] the internal fedora URI
115
130
  def internal_uri
116
131
  self.class.internal_uri(pid)
117
132
  end
118
133
 
119
134
  module ClassMethods
120
135
  # @param [String,Array] uris a single uri (as a string) or a list of uris to convert to pids
121
- # @returns [String] the pid component of the URI
136
+ # @return [String] the pid component of the URI
122
137
  def pids_from_uris(uris)
123
138
  Deprecation.warn(SemanticNode, "pids_from_uris has been deprecated and will be removed in active-fedora 8.0.0", caller)
124
139
  if uris.kind_of? String
@@ -145,13 +160,13 @@ module ActiveFedora
145
160
  end
146
161
 
147
162
  # @param [String] pid the fedora object identifier
148
- # @returns [String] a URI represented as a string
163
+ # @return [String] a URI represented as a string
149
164
  def internal_uri(pid)
150
165
  "info:fedora/#{pid}"
151
166
  end
152
167
 
153
168
  # @param [String] uri a uri (as a string)
154
- # @returns [String] the pid component of the URI
169
+ # @return [String] the pid component of the URI
155
170
  def pid_from_uri(uri)
156
171
  uri.gsub("info:fedora/", "")
157
172
  end