active-fedora 11.1.3 → 11.2.1

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.
Files changed (79) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +3 -2
  3. data/.rubocop_todo.yml +73 -18
  4. data/.travis.yml +4 -4
  5. data/History.txt +6 -0
  6. data/README.md +1 -1
  7. data/active-fedora.gemspec +5 -4
  8. data/lib/active_fedora.rb +3 -3
  9. data/lib/active_fedora/aggregation/list_source.rb +1 -1
  10. data/lib/active_fedora/associations/association.rb +1 -2
  11. data/lib/active_fedora/associations/basic_contains_association.rb +3 -1
  12. data/lib/active_fedora/associations/builder/association.rb +1 -2
  13. data/lib/active_fedora/associations/null_validator.rb +1 -2
  14. data/lib/active_fedora/attached_files.rb +4 -0
  15. data/lib/active_fedora/attributes/property_builder.rb +3 -3
  16. data/lib/active_fedora/containers/container.rb +1 -2
  17. data/lib/active_fedora/file.rb +2 -3
  18. data/lib/active_fedora/file_configurator.rb +2 -2
  19. data/lib/active_fedora/fixity_service.rb +36 -5
  20. data/lib/active_fedora/indexers/null_indexer.rb +1 -2
  21. data/lib/active_fedora/indexing.rb +34 -15
  22. data/lib/active_fedora/indexing/descendant_fetcher.rb +101 -0
  23. data/lib/active_fedora/indexing/map.rb +11 -3
  24. data/lib/active_fedora/indexing_service.rb +6 -1
  25. data/lib/active_fedora/inheritance.rb +1 -1
  26. data/lib/active_fedora/null_logger.rb +2 -4
  27. data/lib/active_fedora/persistence.rb +2 -2
  28. data/lib/active_fedora/property.rb +1 -2
  29. data/lib/active_fedora/rake_support.rb +1 -1
  30. data/lib/active_fedora/rdf/field_map.rb +2 -2
  31. data/lib/active_fedora/rdf/field_map_entry.rb +7 -5
  32. data/lib/active_fedora/rdf/indexing_service.rb +9 -7
  33. data/lib/active_fedora/relation/finder_methods.rb +2 -1
  34. data/lib/active_fedora/solr_service.rb +2 -1
  35. data/lib/active_fedora/type/value.rb +2 -4
  36. data/lib/active_fedora/version.rb +1 -1
  37. data/lib/active_fedora/with_metadata/metadata_node.rb +2 -0
  38. data/spec/integration/associations_spec.rb +8 -8
  39. data/spec/integration/attached_files_spec.rb +1 -2
  40. data/spec/integration/collection_association_spec.rb +1 -1
  41. data/spec/integration/direct_container_spec.rb +2 -2
  42. data/spec/integration/fedora_solr_sync_spec.rb +1 -1
  43. data/spec/integration/generators/fedora_generator_spec.rb +1 -1
  44. data/spec/integration/generators/solr_generator_spec.rb +1 -1
  45. data/spec/integration/has_many_associations_spec.rb +4 -5
  46. data/spec/integration/indexing_spec.rb +21 -1
  47. data/spec/integration/indirect_container_spec.rb +2 -2
  48. data/spec/integration/solr_hit_spec.rb +1 -1
  49. data/spec/integration/versionable_spec.rb +2 -2
  50. data/spec/unit/attached_files_spec.rb +36 -8
  51. data/spec/unit/attributes_spec.rb +5 -13
  52. data/spec/unit/base_spec.rb +2 -2
  53. data/spec/unit/callback_spec.rb +2 -2
  54. data/spec/unit/change_set_spec.rb +1 -2
  55. data/spec/unit/collection_proxy_spec.rb +2 -1
  56. data/spec/unit/core_spec.rb +3 -3
  57. data/spec/unit/default_model_mapper_spec.rb +1 -1
  58. data/spec/unit/file_path_builder_spec.rb +1 -1
  59. data/spec/unit/file_spec.rb +23 -25
  60. data/spec/unit/files_hash_spec.rb +1 -2
  61. data/spec/unit/filter_spec.rb +2 -2
  62. data/spec/unit/fixity_service_spec.rb +65 -5
  63. data/spec/unit/has_and_belongs_to_many_association_spec.rb +1 -2
  64. data/spec/unit/has_many_association_spec.rb +2 -2
  65. data/spec/unit/indexing/map/index_object_spec.rb +25 -0
  66. data/spec/unit/indexing/map_spec.rb +27 -0
  67. data/spec/unit/indexing_spec.rb +1 -2
  68. data/spec/unit/inheritance_spec.rb +28 -1
  69. data/spec/unit/model_classifier_spec.rb +1 -1
  70. data/spec/unit/pathing_spec.rb +1 -2
  71. data/spec/unit/query_result_builder_spec.rb +1 -2
  72. data/spec/unit/query_spec.rb +1 -1
  73. data/spec/unit/rdf/indexing_service_spec.rb +17 -3
  74. data/spec/unit/reflection_spec.rb +2 -2
  75. data/spec/unit/solr_hit_spec.rb +1 -2
  76. data/spec/unit/solr_service_spec.rb +6 -0
  77. data/spec/unit/sparql_insert_spec.rb +1 -1
  78. data/spec/unit/with_metadata/metadata_node_spec.rb +26 -1
  79. metadata +28 -12
@@ -13,6 +13,7 @@ module ActiveFedora
13
13
 
14
14
  eager_autoload do
15
15
  autoload :Map
16
+ autoload :DescendantFetcher
16
17
  end
17
18
 
18
19
  included do
@@ -82,26 +83,44 @@ module ActiveFedora
82
83
  end
83
84
  end
84
85
 
85
- def reindex_everything
86
- descendants = descendant_uris(ActiveFedora.fedora.base_uri)
87
- descendants.shift # Discard the root uri
86
+ # @param [Integer] batch_size - The number of Fedora objects to process for each SolrService.add call. Default 50.
87
+ # @param [Boolean] softCommit - Do we perform a softCommit when we add the to_solr objects to SolrService. Default true.
88
+ # @param [Boolean] progress_bar - If true output progress bar information. Default false.
89
+ # @param [Boolean] final_commit - If true perform a hard commit to the Solr service at the completion of the batch of updates. Default false.
90
+ def reindex_everything(batch_size: 50, softCommit: true, progress_bar: false, final_commit: false)
91
+ # skip root url
92
+ descendants = descendant_uris(ActiveFedora.fedora.base_uri, exclude_uri: true)
93
+
94
+ batch = []
95
+
96
+ progress_bar_controller = ProgressBar.create(total: descendants.count, format: "%t: |%B| %p%% %e") if progress_bar
97
+
88
98
  descendants.each do |uri|
89
99
  logger.debug "Re-index everything ... #{uri}"
90
- ActiveFedora::Base.find(ActiveFedora::Base.uri_to_id(uri)).update_index
100
+
101
+ batch << ActiveFedora::Base.find(ActiveFedora::Base.uri_to_id(uri)).to_solr
102
+
103
+ if (batch.count % batch_size).zero?
104
+ SolrService.add(batch, softCommit: softCommit)
105
+ batch.clear
106
+ end
107
+
108
+ progress_bar_controller.increment if progress_bar_controller
109
+ end
110
+
111
+ if batch.present?
112
+ SolrService.add(batch, softCommit: softCommit)
113
+ batch.clear
91
114
  end
92
- end
93
115
 
94
- def descendant_uris(uri)
95
- resource = Ldp::Resource::RdfSource.new(ActiveFedora.fedora.connection, uri)
96
- # GET could be slow if it's a big resource, we're using HEAD to avoid this problem,
97
- # but this causes more requests to Fedora.
98
- return [] unless resource.head.rdf_source?
99
- immediate_descendant_uris = resource.graph.query(predicate: ::RDF::Vocab::LDP.contains).map { |descendant| descendant.object.to_s }
100
- all_descendants_uris = [uri]
101
- immediate_descendant_uris.each do |descendant_uri|
102
- all_descendants_uris += descendant_uris(descendant_uri)
116
+ if final_commit
117
+ logger.debug "Solr hard commit..."
118
+ SolrService.commit
103
119
  end
104
- all_descendants_uris
120
+ end
121
+
122
+ def descendant_uris(uri, exclude_uri: false)
123
+ DescendantFetcher.new(uri, exclude_self: exclude_uri).descendant_and_self_uris
105
124
  end
106
125
  end
107
126
  end
@@ -0,0 +1,101 @@
1
+ module ActiveFedora
2
+ module Indexing
3
+ # Finds all descendent URIs of a given repo URI (usually the base URI).
4
+ #
5
+ # This is a slow and non-performant thing to do, we need to fetch every single
6
+ # object from the repo.
7
+ #
8
+ # The DescendantFetcher is also capable of partitioning the URIs into "priority" URIs
9
+ # that will be first in the returned list. These prioritized URIs belong to objects
10
+ # with certain hasModel models. This feature is used in some hydra apps that need to
11
+ # index 'permissions' objects before other objects to have the solr indexing work right.
12
+ # And so by default, the prioritized class names are the ones form Hydra::AccessControls,
13
+ # but you can alter the prioritized model name list, or set it to the empty array.
14
+ #
15
+ # DescendantFetcher.new(ActiveFedora.fedora.base_uri).descendent_and_self_uris
16
+ # #=> array including self uri and descendent uris with "prioritized" (by default)
17
+ # Hydra::AccessControls permissions) objects FIRST.
18
+ #
19
+ # Change the default prioritized hasModel names:
20
+ #
21
+ # ActiveFedora::Indexing::DescendantFetcher.default_priority_models = []
22
+ class DescendantFetcher
23
+ HAS_MODEL_PREDICATE = ActiveFedora::RDF::Fcrepo::Model.hasModel
24
+
25
+ class_attribute :default_priority_models, instance_accessor: false
26
+ self.default_priority_models = %w(Hydra::AccessControl Hydra::AccessControl::Permissions).freeze
27
+
28
+ attr_reader :uri, :priority_models
29
+
30
+ def initialize(uri,
31
+ priority_models: self.class.default_priority_models, exclude_self: false)
32
+ @uri = uri
33
+ @priority_models = priority_models
34
+ @exclude_self = exclude_self
35
+ end
36
+
37
+ def descendant_and_self_uris
38
+ partitioned = descendant_and_self_uris_partitioned
39
+ partitioned[:priority] + partitioned[:other]
40
+ end
41
+
42
+ # returns a hash where key :priority is an array of all prioritized
43
+ # type objects, key :other is an array of the rest.
44
+ def descendant_and_self_uris_partitioned
45
+ resource = Ldp::Resource::RdfSource.new(ActiveFedora.fedora.connection, uri)
46
+ # GET could be slow if it's a big resource, we're using HEAD to avoid this problem,
47
+ # but this causes more requests to Fedora.
48
+ return partitioned_uris unless resource.head.rdf_source?
49
+
50
+ add_self_to_partitioned_uris unless @exclude_self
51
+
52
+ immediate_descendant_uris = rdf_graph.query(predicate: ::RDF::Vocab::LDP.contains).map { |descendant| descendant.object.to_s }
53
+ immediate_descendant_uris.each do |descendant_uri|
54
+ self.class.new(
55
+ descendant_uri,
56
+ priority_models: priority_models
57
+ ).descendant_and_self_uris_partitioned.tap do |descendant_partitioned|
58
+ partitioned_uris[:priority].concat descendant_partitioned[:priority]
59
+ partitioned_uris[:other].concat descendant_partitioned[:other]
60
+ end
61
+ end
62
+ partitioned_uris
63
+ end
64
+
65
+ protected
66
+
67
+ def rdf_resource
68
+ @rdf_resource ||= Ldp::Resource::RdfSource.new(ActiveFedora.fedora.connection, uri)
69
+ end
70
+
71
+ def rdf_graph
72
+ @rdf_graph ||= rdf_resource.graph
73
+ end
74
+
75
+ def partitioned_uris
76
+ @partitioned_uris ||= {
77
+ priority: [],
78
+ other: []
79
+ }
80
+ end
81
+
82
+ def rdf_graph_models
83
+ rdf_graph.query(predicate: HAS_MODEL_PREDICATE).collect(&:object).collect do |rdf_object|
84
+ rdf_object.to_s if rdf_object.literal?
85
+ end.compact
86
+ end
87
+
88
+ def prioritized_object?
89
+ priority_models.present? && (rdf_graph_models & priority_models).count > 0
90
+ end
91
+
92
+ def add_self_to_partitioned_uris
93
+ if prioritized_object?
94
+ partitioned_uris[:priority] << rdf_resource.subject
95
+ else
96
+ partitioned_uris[:other] << rdf_resource.subject
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -11,7 +11,15 @@ module ActiveFedora::Indexing
11
11
  end
12
12
 
13
13
  def dup
14
- self.class.new(@hash.deep_dup)
14
+ self.class.new(to_hash)
15
+ end
16
+
17
+ def merge(new_hash)
18
+ self.class.new(to_hash.merge(new_hash))
19
+ end
20
+
21
+ def to_hash
22
+ @hash.deep_dup
15
23
  end
16
24
 
17
25
  # this enables a cleaner API for solr integration
@@ -19,8 +27,8 @@ module ActiveFedora::Indexing
19
27
  attr_accessor :data_type, :behaviors, :term
20
28
  attr_reader :key
21
29
 
22
- def initialize(name, &_block)
23
- @behaviors = []
30
+ def initialize(name, behaviors: [], &_block)
31
+ @behaviors = behaviors
24
32
  @data_type = :string
25
33
  @key = name
26
34
  yield self if block_given?
@@ -61,7 +61,12 @@ module ActiveFedora
61
61
  # Serialize the resource's RDF relationships to solr
62
62
  # @param [Hash] solr_doc @deafult an empty Hash
63
63
  def solrize_rdf_assertions(solr_doc = {})
64
- solr_doc.merge rdf_service.new(object).generate_solr_document
64
+ solr_doc.merge rdf_indexer.generate_solr_document
65
+ end
66
+
67
+ # @return IndexingService
68
+ def rdf_indexer
69
+ rdf_service.new(object, object.class.index_config)
65
70
  end
66
71
  end
67
72
  end
@@ -12,7 +12,7 @@ module ActiveFedora
12
12
  # If B < A and C < B and if A is an abstract_class then both B.base_class
13
13
  # and C.base_class would return B as the answer since A is an abstract_class.
14
14
  def base_class
15
- return File if self == File || superclass == File
15
+ return File if self <= File
16
16
 
17
17
  unless self <= Base
18
18
  raise ActiveFedoraError, "#{name} doesn't belong in a hierarchy descending from ActiveFedora"
@@ -1,11 +1,9 @@
1
1
  module ActiveFedora
2
2
  class NullLogger < Logger
3
- def initialize(*)
4
- end
3
+ def initialize(*); end
5
4
 
6
5
  # allows all the usual logger method calls (warn, info, error, etc.)
7
- def add(*)
8
- end
6
+ def add(*); end
9
7
 
10
8
  # In the NullLogger there are no levels, so none of these should be true.
11
9
  [:debug?, :info?, :warn?, :error?, :fatal?].each do |method_name|
@@ -205,8 +205,7 @@ module ActiveFedora
205
205
  end
206
206
 
207
207
  # Override to tie in an ID minting service
208
- def assign_id
209
- end
208
+ def assign_id; end
210
209
 
211
210
  # This is only used when creating a new record. If the object doesn't have an id
212
211
  # and assign_id can mint an id for the object, then assign it to the resource.
@@ -228,6 +227,7 @@ module ActiveFedora
228
227
  root_resource_path
229
228
  end
230
229
 
230
+ # Check to see if the :base_path (from fedora.yml) exists in Fedora. If it doesn't exist, then create it.
231
231
  def init_root_path
232
232
  path = root_resource_path.gsub(/^\//, "")
233
233
  ActiveFedora.fedora.connection.head(path)
@@ -7,7 +7,6 @@ module ActiveFedora
7
7
  @instance_variable_name = "@#{@name}"
8
8
  end
9
9
 
10
- def field
11
- end
10
+ def field; end
12
11
  end
13
12
  end
@@ -12,7 +12,7 @@ def with_server(environment)
12
12
  # setting port: nil assigns a random port.
13
13
  solr_defaults = { port: nil, verbose: true, managed: true }
14
14
  fcrepo_defaults = { port: nil, verbose: true, managed: true,
15
- enable_jms: false, fcrepo_home_dir: "fcrepo4-#{environment}-data" }
15
+ enable_jms: false, fcrepo_home_dir: "tmp/fcrepo4-#{environment}-data" }
16
16
 
17
17
  SolrWrapper.wrap(load_config(:solr, environment, solr_defaults)) do |solr|
18
18
  ENV["SOLR_#{environment.upcase}_PORT"] = solr.port.to_s
@@ -15,8 +15,8 @@ module ActiveFedora::RDF
15
15
 
16
16
  # Inserts each solr field map configuration into the FieldMap class
17
17
  # @param [Symbol] name the name of the property on the object that we're indexing
18
- # @param [Object] index_field_config an instance of ActiveFedora::Indexing::Map::IndexObject
19
- # @param [Object] object the instance of ActiveFedora::Base which is being indexed into Solr
18
+ # @param [ActiveFedora::Indexing::Map::IndexObject] index_field_config describes how the object should be indexed
19
+ # @param [ActiveFedora::Base] object the object to be indexed into Solr
20
20
  def insert(name, index_field_config, object)
21
21
  self[index_field_config.key.to_s] ||= FieldMapEntry.new
22
22
  PolymorphicBuilder.new(self[index_field_config.key.to_s], index_field_config, object, name).build
@@ -3,9 +3,10 @@ module ActiveFedora::RDF
3
3
  # It might be possible for two properties to share a single field map entry if they use the same solr key.
4
4
  # @attribute [Symbol] type the data type hint for Solrizer
5
5
  # @attribute [Array] behaviors the indexing hints such as :stored_searchable or :symbol
6
- # @attribute [Array] values the actual values that get sent to solr
6
+ # @!attribute [w] values the raw values
7
7
  class FieldMapEntry
8
- attr_accessor :type, :behaviors, :values
8
+ attr_accessor :type, :behaviors
9
+ attr_writer :values
9
10
 
10
11
  def initialize
11
12
  @behaviors = []
@@ -15,14 +16,15 @@ module ActiveFedora::RDF
15
16
  # Merges any existing values for solr fields with new, incoming values and ensures that resulting values are unique.
16
17
  # @param [Symbol] type the data type for the field such as :string, :date, :integer
17
18
  # @param [Array] behaviors Solrizer's behaviors for indexing such as :stored_searhable, :symbol
18
- # @param [Array] values existing values for the solr field
19
- def merge!(type, behaviors, values)
19
+ # @param [Array] new_values values to append into the existing solr field
20
+ def merge!(type, behaviors, new_values)
20
21
  self.type ||= type
21
22
  self.behaviors += behaviors
22
23
  self.behaviors.uniq!
23
- self.values += values
24
+ self.values += new_values
24
25
  end
25
26
 
27
+ # @return [Array] the actual values that get sent to solr
26
28
  def values
27
29
  @values.map do |value|
28
30
  ValueCaster.new(value).value
@@ -6,11 +6,17 @@ module ActiveFedora::RDF
6
6
  # @see ActiveFedora::IndexingService
7
7
  class IndexingService
8
8
  include Solrizer::Common
9
- attr_reader :object
9
+ attr_reader :object, :index_config
10
10
 
11
- # @param [#resource, #rdf_subject] obj the object to build an solr document for. Its class must respond to 'properties' and 'index_config'
12
- def initialize(obj)
11
+ # @param [#resource, #rdf_subject] obj the object to build an solr document for. Its class must respond to 'properties'
12
+ # @param [ActiveFedora::Indexing::Map] index_config the configuration to use to map object values to index document values
13
+ def initialize(obj, index_config = nil)
14
+ unless index_config
15
+ Deprecation.warn(self, "initializing ActiveFedora::RDF::IndexingService without an index_config is deprecated and will be removed in ActiveFedora 13.0")
16
+ index_config = obj.class.index_config
17
+ end
13
18
  @object = obj
19
+ @index_config = index_config
14
20
  end
15
21
 
16
22
  # Creates a solr document hash for the rdf assertions of the {#object}
@@ -69,10 +75,6 @@ module ActiveFedora::RDF
69
75
  object.resource
70
76
  end
71
77
 
72
- def index_config
73
- object.class.index_config
74
- end
75
-
76
78
  # returns the field map instance
77
79
  def fields
78
80
  field_map_class.new do |field_map|
@@ -189,7 +189,8 @@ module ActiveFedora
189
189
  protected
190
190
 
191
191
  def load_from_fedora(id, cast)
192
- raise ActiveFedora::ObjectNotFoundError if id.empty?
192
+ raise ActiveFedora::ObjectNotFoundError, "No ID provided for #{klass.name}." if id.empty?
193
+
193
194
  resource = ActiveFedora.fedora.ldp_resource_service.build(klass, id)
194
195
  raise_record_not_found_exception!(id) if resource.new?
195
196
  class_to_load(resource, cast).allocate.init_with_resource(resource) # Triggers the find callback
@@ -2,6 +2,7 @@ require 'rsolr'
2
2
 
3
3
  module ActiveFedora
4
4
  class SolrService
5
+ attr_reader :options
5
6
  attr_writer :conn
6
7
 
7
8
  MAX_ROWS = 10_000
@@ -64,7 +65,7 @@ module ActiveFedora
64
65
  SolrService.get(query, args)['response']['numFound'].to_i
65
66
  end
66
67
 
67
- # @param [Hash] doc the document to index
68
+ # @param [Hash] doc the document to index, or an array of docs
68
69
  # @param [Hash] params
69
70
  # :commit => commits immediately
70
71
  # :softCommit => commit to memory, but don't flush to disk
@@ -11,8 +11,7 @@ module ActiveFedora
11
11
  @limit = limit
12
12
  end
13
13
 
14
- def type # :nodoc:
15
- end
14
+ def type; end
16
15
 
17
16
  # Converts a value from database input to the appropriate ruby type. The
18
17
  # return value of this method will be returned from
@@ -102,8 +101,7 @@ module ActiveFedora
102
101
  [self.class, precision, scale, limit].hash
103
102
  end
104
103
 
105
- def assert_valid_value(*)
106
- end
104
+ def assert_valid_value(*); end
107
105
 
108
106
  private
109
107
 
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "11.1.3".freeze
2
+ VERSION = "11.2.1".freeze
3
3
  end
@@ -36,6 +36,7 @@ module ActiveFedora
36
36
  end
37
37
 
38
38
  def ldp_source
39
+ @ldp_source ||= LdpResource.new(ldp_connection, nil) if file.new_record?
39
40
  @ldp_source ||= LdpResource.new(ldp_connection, metadata_uri)
40
41
  end
41
42
 
@@ -47,6 +48,7 @@ module ActiveFedora
47
48
  raise "Save the file first" if file.new_record?
48
49
  SparqlInsert.new(changes_for_update, file.uri).execute(metadata_uri)
49
50
  @ldp_source = nil
51
+ @metadata_uri = nil
50
52
  true
51
53
  end
52
54
 
@@ -16,8 +16,8 @@ describe ActiveFedora::Base do
16
16
  Object.send(:remove_const, :Person)
17
17
  end
18
18
 
19
- let(:person) { Person.create }
20
19
  subject(:book) { Book.new(author: person) }
20
+ let(:person) { Person.create }
21
21
 
22
22
  it "goes" do
23
23
  book.save
@@ -511,8 +511,7 @@ describe ActiveFedora::Base do
511
511
  after_count(m.reload.library_books.count)
512
512
  end
513
513
 
514
- def say_hi(_var)
515
- end
514
+ def say_hi(_var); end
516
515
  end
517
516
  class Page < ActiveFedora::Base
518
517
  has_many :library_books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
@@ -524,14 +523,15 @@ describe ActiveFedora::Base do
524
523
  end
525
524
 
526
525
  describe "removing association" do
527
- let(:p1) { Page.create }
528
- let(:p2) { Page.create }
529
526
  subject(:book) do
530
527
  book = LibraryBook.create
531
528
  book.pages << p1 << p2
532
529
  book.save!
533
530
  book
534
531
  end
532
+ let(:p1) { Page.create }
533
+ let(:p2) { Page.create }
534
+
535
535
  it "saves between the before and after hooks" do
536
536
  expect(book).to receive(:before_count).with(1)
537
537
  expect(book).to receive(:after_count).with(0)
@@ -582,7 +582,7 @@ describe ActiveFedora::Base do
582
582
  Object.send(:remove_const, :MediaObject)
583
583
  end
584
584
 
585
- it "it should find the reflection that bears the predicate" do
585
+ it "finds the reflection that bears the predicate" do
586
586
  expect(MediaObject.new.association(:baubles).send(:find_reflection)).to eq Bauble._reflect_on_association(:media_object)
587
587
  end
588
588
  end
@@ -602,7 +602,7 @@ describe ActiveFedora::Base do
602
602
  Object.send(:remove_const, :MediaObject)
603
603
  end
604
604
 
605
- it "it should find the reflection that bears the predicate" do
605
+ it "finds the reflection that bears the predicate" do
606
606
  expect(MediaObject.new.association(:parts).send(:find_reflection)).to eq MasterFile._reflect_on_association(:media_object)
607
607
  end
608
608
  end
@@ -622,7 +622,7 @@ describe ActiveFedora::Base do
622
622
  Object.send(:remove_const, :MediaObject)
623
623
  end
624
624
 
625
- it "it should find the reflection that bears the predicate" do
625
+ it "finds the reflection that bears the predicate" do
626
626
  expect(MediaObject.new.association(:baubles).send(:find_reflection)).to eq MediaObject._reflect_on_association(:baubles)
627
627
  end
628
628
  end