active-fedora 2.3.4 → 2.3.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active-fedora (2.3.4)
4
+ active-fedora (2.3.5)
5
5
  activeresource
6
6
  equivalent-xml
7
7
  facets
@@ -17,7 +17,7 @@ PATH
17
17
  GEM
18
18
  remote: http://rubygems.org/
19
19
  specs:
20
- RedCloth (4.2.7)
20
+ RedCloth (4.2.8)
21
21
  activeresource (2.3.14)
22
22
  activesupport (= 2.3.14)
23
23
  activesupport (2.3.14)
@@ -26,7 +26,7 @@ GEM
26
26
  daemons (1.1.4)
27
27
  equivalent-xml (0.2.7)
28
28
  nokogiri (>= 1.4.3)
29
- facets (2.9.1)
29
+ facets (2.9.2)
30
30
  fastercsv (1.5.4)
31
31
  jettywrapper (0.0.10)
32
32
  logger
@@ -39,7 +39,8 @@ GEM
39
39
  mocha (0.9.12)
40
40
  multipart-post (1.1.2)
41
41
  nokogiri (1.5.0)
42
- om (1.3.0)
42
+ om (1.4.0)
43
+ mediashelf-loggable
43
44
  nokogiri (>= 1.4.2)
44
45
  rake (0.9.2)
45
46
  rbx-require-relative (0.0.5)
@@ -1,4 +1,20 @@
1
+ 2.3.7
2
+
3
+ HYDRA-650 -- Fixed relationship inheritance (Rick Johnson)
4
+
5
+ 2.3.6
6
+
7
+ YANKED
8
+ Removed Bundler.require, which was causing odd dependency order resolving.
9
+
10
+ 2.3.5
11
+
12
+ YANKED
13
+ branched so that trunk now require rails 3.
14
+ Named finders HYDRA-541 (Rick Johnson)
15
+
1
16
  2.3.4
17
+
2
18
  moved dirty assignment to NokogiriDatastream#update_values; added test (Benjamin Armintor)
3
19
  Fixed HYDRA-590
4
20
 
@@ -1,6 +1,6 @@
1
1
  h2. Description
2
2
 
3
- RubyFedora and ActiveFedora provide a set of Ruby gems for creating and managing objects in the Fedora Repository Architecture ("http://fedora-commons.org":http://fedora-commons.org). ActiveFedora is loosely based on "ActiveRecord" in Rails.
3
+ RubyFedora and ActiveFedora provide a set of Ruby gems for creating and managing objects in the Fedora Repository Architecture ("http://fedora-commons.org":http://fedora-commons.org). ActiveFedora is loosely based on "ActiveRecord" in Rails. This version of ActiveFedora depends on Rails 2.3.11 and has been superceeded by ActiveFedora 3.x which requires Rails 3.
4
4
 
5
5
  h2. Getting Help
6
6
 
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.add_dependency('solr-ruby', '>= 0.0.6')
19
19
  s.add_dependency('xml-simple', '>= 1.0.12')
20
20
  s.add_dependency('mime-types', '>= 1.16')
21
- s.add_dependency('multipart-post', "1.1.2")
21
+ s.add_dependency('multipart-post', "= 1.1.2")
22
22
  s.add_dependency('nokogiri')
23
23
  s.add_dependency('om', '>= 1.0')
24
24
  s.add_dependency('solrizer', '>1.0.0')
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
- require "bundler/setup"
3
- Bundler.require(:default)
2
+ # require "bundler/setup"
3
+ # Bundler.require(:default)
4
4
 
5
5
  gem 'solr-ruby'
6
6
  require "loggable"
@@ -68,14 +68,14 @@ module ActiveFedora #:nodoc:
68
68
  # 2. If it does not find a solr.yml and the fedora.yml contains a solr url, it will raise an configuration error
69
69
  # 3. If it does not find a solr.yml and the fedora.yml does not contain a solr url, it will look in: +Rails.root+/config, +current working directory+/config, then the solr.yml shipped with gem
70
70
  def self.init( options={} )
71
- logger.level = Logger::ERROR
71
+ logger.level = Logger::ERROR if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
72
72
  # Make config_options into a Hash if nil is passed in as the value
73
73
  options = {} if options.nil?
74
74
 
75
75
  # For backwards compatibility, handle cases where config_path (a String) is passed in as the argument rather than a config_options hash
76
76
  # In all other cases, set config_path to config_options[:config_path], which is ok if it's nil
77
77
  if options.is_a? String
78
- logger.warn "DEPRECATION WARNING: Calling ActiveFedora.init with a path as an argument is deprecated. Use ActiveFedora.init(:config_path=>#{options})"
78
+ logger.warn "DEPRECATION WARNING: Calling ActiveFedora.init with a path as an argument is deprecated. Use ActiveFedora.init(:fedora_config_path=>#{options})"
79
79
  @config_options = {:fedora_config_path=>options}
80
80
  else
81
81
  @config_options = options
@@ -0,0 +1,889 @@
1
+ module ActiveFedora
2
+ # This module is meant to extend semantic node to add functionality based on a relationship's name
3
+ # It is meant to turn a relationship into just another attribute in a model.
4
+ # The notion of a "relationship name" is used _internally_ to distinguish between the relationships you've set up using has_relationship and the implicit relationships that are based on the predicates themselves.
5
+ #
6
+ # @example ActiveFedora
7
+ # has_relationship "parents", :is_member_of
8
+ #
9
+ # obj.parents is a relationship in ActiveFedora while :is_member_of is the literal RDF relationship in Fedora
10
+ #
11
+ # There are also several helper methods created for any relationship declared in ActiveFedora. For the above example
12
+ # the following methods are created:
13
+ #
14
+ # obj.parents_append(object) Appends an object to the "parents" relationship
15
+ # obj.parents_remove(object) Removes an object from the "parents" relationship
16
+ # obj.parents_query Returns the query used against solr to retrieve objects linked via the "parents" relationship
17
+ #
18
+ # Note: ActiveFedora relationships can reflect filters ...
19
+ # If you define the solr_fq parameter in your has_relationship call some objects will be filtered out:
20
+ #
21
+ # has_relationship "parents", :is_member_of, :solr_fq=>"eyes:blue"
22
+ #
23
+ # Then obj.parents will only return parents where their eyes are blue.
24
+ module RelationshipsHelper
25
+
26
+ include MediaShelfClassLevelInheritableAttributes
27
+ ms_inheritable_attributes :class_relationships_desc
28
+
29
+ def self.included(klass)
30
+ klass.extend(ClassMethods)
31
+ end
32
+
33
+
34
+ # ** EXPERIMENTAL **
35
+ #
36
+ # Return array of objects for a given relationship name
37
+ # @param [String] Name of relationship to find
38
+ # @return [Array] Returns array of objects linked via the relationship name given
39
+ def find_relationship_by_name(name)
40
+ rels = nil
41
+ if inbound_relationship_names.include?(name)
42
+ rels = relationships_by_name(false)[:inbound][name]
43
+ elsif outbound_relationship_names.include?(name)
44
+ rels = relationships_by_name[:self][name]
45
+ end
46
+ rels = [] if rels.nil?
47
+ return rels
48
+ end
49
+
50
+ # ** EXPERIMENTAL **
51
+ #
52
+ # Internal method that ensures a relationship subject such as :self and :inbound
53
+ # exist within the relationships_desc hash tracking relationships metadata.
54
+ # This method just calls the class method counterpart of this method.
55
+ # @param [Symbol] Subject name to register (will probably be something like :self or :inbound)
56
+ def register_relationship_desc_subject(subject)
57
+ self.class.register_relationship_desc_subject(subject)
58
+ end
59
+
60
+ # ** EXPERIMENTAL **
61
+ #
62
+ # Internal method that adds a relationship description for a
63
+ # relationship name and predicate pair to either an outbound (:self)
64
+ # or inbound (:inbound) relationship types. This method just calls the class method counterpart of this method.
65
+ # @param [Symbol] Subject name to register
66
+ # @param [String] Name of relationship being registered
67
+ # @param [Symbol] Fedora ontology predicate to use
68
+ # @param [Hash] Any options passed to has_relationship such as :type, :solr_fq, etc.
69
+ def register_relationship_desc(subject, name, predicate, opts={})
70
+ self.class.register_relationship_desc(subject, name, predicate, opts)
71
+ end
72
+
73
+ # ** EXPERIMENTAL **
74
+ #
75
+ # Gets the relationships hash with subject mapped to relationship
76
+ # names instead of relationship predicates (unlike the "relationships" method in SemanticNode)
77
+ # It has an optional parameter of outbound_only that defaults true.
78
+ # If false it will include inbound relationships in the results.
79
+ # Also, it will only reload outbound relationships if the relationships hash has changed
80
+ # since the last time this method was called.
81
+ # @param [Boolean] if false it will include inbound relationships (defaults to true)
82
+ # @return [Hash] Returns a hash of subject name (:self or :inbound) mapped to nested hashs of each relationship name mapped to an Array of objects linked via the relationship
83
+ def relationships_by_name(outbound_only=true)
84
+ #make sure to update if relationships have been updated
85
+ if @relationships_are_dirty == true
86
+ @relationships_by_name = relationships_by_name_from_class()
87
+ @relationships_are_dirty = false
88
+ end
89
+
90
+ #this will get called normally on first fetch if relationships are not dirty
91
+ @relationships_by_name ||= relationships_by_name_from_class()
92
+ outbound_only ? @relationships_by_name : @relationships_by_name.merge(:inbound=>inbound_relationships_by_name)
93
+ end
94
+
95
+ # ** EXPERIMENTAL **
96
+ #
97
+ # Gets relationships by name from the class using the current relationships hash
98
+ # and relationship name,predicate pairs.
99
+ # @return [Hash] returns the outbound relationships with :self mapped to nested hashs of each relationship name mapped to an Array of objects linked via the relationship
100
+ def relationships_by_name_from_class()
101
+ rels = {}
102
+ relationship_predicates.each_pair do |subj, names|
103
+ if relationships.has_key?(subj)
104
+ rels[subj] = {}
105
+ names.each_pair do |name, predicate|
106
+ rels[subj][name] = (relationships[subj].has_key?(predicate) ? relationships[subj][predicate] : [])
107
+ end
108
+ end
109
+ end
110
+ return rels
111
+ end
112
+
113
+
114
+ # ** EXPERIMENTAL **
115
+ #
116
+ # Return hash of relationships_by_name defined within other objects' RELS-EXT
117
+ # It returns a hash of relationship name to arrays of objects. It requeries
118
+ # solr each time this method is called.
119
+ # @return [Hash] Return hash of each relationship name mapped to an Array of objects linked to this object via inbound relationships
120
+ def inbound_relationships_by_name
121
+ rels = {}
122
+ if relationships_desc.has_key?(:inbound)&&!relationships_desc[:inbound].empty?()
123
+ inbound_rels = inbound_relationships
124
+
125
+ if relationship_predicates.has_key?(:inbound)
126
+ relationship_predicates[:inbound].each do |name, predicate|
127
+ rels[name] = inbound_rels.has_key?(predicate) ? inbound_rels[predicate] : []
128
+ end
129
+ end
130
+ end
131
+ return rels
132
+ end
133
+
134
+ # ** EXPERIMENTAL **
135
+ #
136
+ # Return hash of outbound relationship names and predicate pairs
137
+ # @return [Hash] A hash of outbound relationship names mapped to predicates used
138
+ def outbound_relationship_predicates
139
+ relationship_predicates.has_key?(:self) ? relationship_predicates[:self] : {}
140
+ end
141
+
142
+ # ** EXPERIMENTAL **
143
+ #
144
+ # Return hash of inbound relationship names and predicate pairs
145
+ # @return [Hash] A hash of inbound relationship names mapped to predicates used
146
+ def inbound_relationship_predicates
147
+ relationship_predicates.has_key?(:inbound) ? relationship_predicates[:inbound] : {}
148
+ end
149
+
150
+ # ** EXPERIMENTAL **
151
+ #
152
+ # Return hash of relationship names and predicate pairs (inbound and outbound).
153
+ # This method calls the class method version of this method to get the static settings
154
+ # defined in the class definition.
155
+ # @return [Hash] A hash of relationship names (inbound and outbound) mapped to predicates used
156
+ def relationship_predicates
157
+ @relationship_predicates ||= relationship_predicates_from_class
158
+ end
159
+
160
+ # ** EXPERIMENTAL **
161
+ #
162
+ # Return hash of relationship names and predicate pairs from class.
163
+ # It retrieves this information via the relationships_desc hash in the class.
164
+ # @return [Hash] A hash of relationship names (inbound and outbound) mapped to predicates used
165
+ def relationship_predicates_from_class
166
+ rels = {}
167
+ relationships_desc.each_pair do |subj, names|
168
+ rels[subj] = {}
169
+ names.each_pair do |name, args|
170
+ rels[subj][name] = args[:predicate]
171
+ end
172
+ end
173
+ return rels
174
+ end
175
+
176
+ # ** EXPERIMENTAL **
177
+ #
178
+ # Return array all relationship names
179
+ # @return [Array] of relationship names for relationships declared via has_relationship in the class
180
+ def relationship_names
181
+ names = []
182
+ relationships_desc.each_key do |subject|
183
+ names = names.concat(relationships_desc[subject].keys)
184
+ end
185
+ names
186
+ end
187
+
188
+ # ** EXPERIMENTAL **
189
+ #
190
+ # Return array of relationship names for all inbound relationships (coming from other objects' RELS-EXT and Solr)
191
+ # @return [Array] of inbound relationship names for relationships declared via has_relationship in the class
192
+ def inbound_relationship_names
193
+ relationships_desc.has_key?(:inbound) ? relationships_desc[:inbound].keys : []
194
+ end
195
+
196
+ # ** EXPERIMENTAL **
197
+ #
198
+ # Return array of relationship names for all outbound relationships (coming from this object's RELS-EXT)
199
+ # @return [Array] of outbound relationship names for relationships declared via has_relationship in the class
200
+ def outbound_relationship_names
201
+ relationships_desc.has_key?(:self) ? relationships_desc[:self].keys : []
202
+ end
203
+
204
+ # ** EXPERIMENTAL **
205
+ #
206
+ # Return hash of relationships_by_name defined within this object's RELS-EXT
207
+ # It returns a hash of relationship name to arrays of objects
208
+ # @return [Hash] Return hash of each relationship name mapped to an Array of objects linked to this object via outbound relationships
209
+ def outbound_relationships_by_name
210
+ relationships_desc.has_key?(:self) ? relationships_by_name[:self] : {}
211
+ end
212
+
213
+ # ** EXPERIMENTAL **
214
+ #
215
+ # Returns true if the given relationship name is a relationship
216
+ # @param [String] Name of relationship
217
+ # @param [Boolean] If false checks inbound relationships as well (defaults to true)
218
+ def is_relationship_name?(name, outbound_only=true)
219
+ if outbound_only
220
+ outbound_relationship_names.include?(name)
221
+ else
222
+ (outbound_relationship_names.include?(name)||inbound_relationship_names.include?(name))
223
+ end
224
+ end
225
+
226
+ # ** EXPERIMENTAL **
227
+ #
228
+ # Return hash that persists relationship metadata defined by has_relationship calls
229
+ # @return [Hash] Hash of relationship subject (:self or :inbound) mapped to nested hashs of each relationship name mapped to another hash relationship options
230
+ # @example For the following relationship
231
+ #
232
+ # has_relationship "audio_records", :has_part, :type=>AudioRecord
233
+ #
234
+ # Results in the following returned by relationships_desc
235
+ # {:self=>{"audio_records"=>{:type=>AudioRecord, :singular=>nil, :predicate=>:has_part, :inbound=>false}}}
236
+ def relationships_desc
237
+ @relationships_desc ||= relationships_desc_from_class
238
+ end
239
+
240
+ # ** EXPERIMENTAL **
241
+ #
242
+ # Get class instance variable relationships_desc that holds has_relationship metadata
243
+ # @return [Hash] Hash of relationship subject (:self or :inbound) mapped to nested hashs of each relationship name mapped to another hash relationship options
244
+ def relationships_desc_from_class
245
+ self.class.relationships_desc
246
+ end
247
+
248
+ # ** EXPERIMENTAL **
249
+ #
250
+ # Return the value of :type for the relationship for name passed in if defined
251
+ # It defaults to ActiveFedora::Base.
252
+ # @return [Class] the name of the class defined for a relationship by the :type option if present
253
+ def relationship_model_type(name)
254
+ if is_relationship_name?(name,true)
255
+ subject = outbound_relationship_names.include?(name)? :self : :inbound
256
+ if relationships_desc[subject][name].has_key?(:type)
257
+ return class_from_name(relationships_desc[subject][name][:type])
258
+ end
259
+ end
260
+ return nil
261
+ end
262
+
263
+ # ** EXPERIMENTAL **
264
+ #
265
+ # Add an outbound relationship for given relationship name
266
+ # See ActiveFedora::SemanticNode::ClassMethods.has_relationship
267
+ # @param [String] Name of relationship
268
+ # @param [ActiveFedora::Base] object to add to the relationship (expects ActvieFedora::Base to be an ancestor)
269
+ # @return [Boolean] returns true if add operation successful
270
+ def add_relationship_by_name(name, object)
271
+ if is_relationship_name?(name,true)
272
+ if relationships_desc[:self][name].has_key?(:type)
273
+ klass = class_from_name(relationships_desc[:self][name][:type])
274
+ unless klass.nil?
275
+ (assert_conforms_to 'object', object, klass)
276
+ end
277
+ end
278
+ #r = ActiveFedora::Relationship.new({:subject=>:self,:predicate=>outbound_relationship_predicates[name],:object=>object})
279
+ #add_relationship(r)
280
+ add_relationship(outbound_relationship_predicates[name],object)
281
+ else
282
+ false
283
+ end
284
+ end
285
+
286
+ # ** EXPERIMENTAL **
287
+ #
288
+ # Remove an object for the given relationship name
289
+ # @param [String] Relationship name
290
+ # @param [ActiveFedora::Base] object to remove
291
+ # @return [Boolean] return true if remove operation successful
292
+ def remove_relationship_by_name(name, object)
293
+ if is_relationship_name?(name,true)
294
+ remove_relationship(outbound_relationship_predicates[name],object)
295
+ else
296
+ return false
297
+ end
298
+ end
299
+
300
+ # ** EXPERIMENTAL **
301
+ #
302
+ # Throws an assertion error if conforms_to? returns false for object and model_class
303
+ # @param [String] Name of object (just label for output)
304
+ # @param [ActiveFedora::Base] Expects to be an object that has ActiveFedora::Base as an ancestor of its class
305
+ # @param [Class] The model class used in conforms_to? check on object
306
+ def assert_conforms_to(name, object, model_class)
307
+ raise "Assertion failure: #{name}: #{object.pid} does not have model #{model_class}, it has model #{relationships[:self][:has_model]}" unless object.conforms_to?(model_class)
308
+ end
309
+
310
+ # ** EXPERIMENTAL **
311
+ #
312
+ # Checks that this object is matches the model class passed in.
313
+ # It requires two steps to pass to return true
314
+ # 1. It has a hasModel relationship of the same model
315
+ # 2. kind_of? returns true for the model passed in
316
+ # This method can most often be used to detect if an object from Fedora that was created
317
+ # with a different model was then used to populate this object.
318
+ # @param [Class] the model class name to check if an object conforms_to that model
319
+ # @return [Boolean] true if this object conforms to the given model name
320
+ def conforms_to?(model_class)
321
+ if self.kind_of?(model_class)
322
+ #check has model and class match
323
+ if relationships[:self].has_key?(:has_model)
324
+ r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:has_model, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(self.class))
325
+ if relationships[:self][:has_model].first.to_s.eql?(r.object.to_s)
326
+ return true
327
+ else
328
+ raise "has_model relationship check failed for model #{model_class} raising exception, expected: '#{r.object.to_s}' actual: '#{relationships[:self][:has_model].to_s}'"
329
+ end
330
+ else
331
+ raise "has_model relationship does not exist for model #{model_class} check raising exception"
332
+ end
333
+ else
334
+ raise "kind_of? check failed for model #{model_class}, actual #{self.class} raising exception"
335
+ end
336
+ return false
337
+ end
338
+
339
+ # Returns a Class symbol for the given string for the class name
340
+ # @param [String] the class name as a string
341
+ # @return [Class] the class as a Class object
342
+ def class_from_name(name)
343
+ klass = name.to_s.split('::').inject(Kernel) {|scope, const_name|
344
+ scope.const_get(const_name)}
345
+ (!klass.nil? && klass.is_a?(::Class)) ? klass : nil
346
+ end
347
+
348
+ # Call this method to return the query used against solr to retrieve any
349
+ # objects linked via the relationship name given.
350
+ #
351
+ # Instead of this method you can also use the helper method
352
+ # [relationship_name]_query, i.e. method "parts_query" for relationship "parts" to return the same value
353
+ # @param [String] The name of the relationship defined in the model
354
+ # @return [String] The query used when querying solr for objects for this relationship
355
+ # @example
356
+ # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
357
+ # #points to all parents linked via is_member_of
358
+ # has_relationship "parents", :is_member_of
359
+ # #returns only parents that have a level value set to "series"
360
+ # has_relationship "series_parents", :is_member_of, :solr_fq=>level_t:series"
361
+ # end
362
+ # s = SampleAFObjRelationshipFilterQuery.new
363
+ # obj = ActiveFedora::Base.new
364
+ # s.parents_append(obj)
365
+ # s.series_parents_query
366
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
367
+ # SampleAFObjRelationshipFilterQuery.relationship_query("series_parents")
368
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
369
+ def relationship_query(relationship_name)
370
+ query = ""
371
+ if self.class.is_bidirectional_relationship?(relationship_name)
372
+ id_array = []
373
+ predicate = outbound_relationship_predicates["#{relationship_name}_outbound"]
374
+ if !outbound_relationships[predicate].nil?
375
+ outbound_relationships[predicate].each do |rel|
376
+ id_array << rel.gsub("info:fedora/", "")
377
+ end
378
+ end
379
+ query = self.class.bidirectional_relationship_query(pid,relationship_name,id_array)
380
+ elsif outbound_relationship_names.include?(relationship_name)
381
+ id_array = []
382
+ predicate = outbound_relationship_predicates[relationship_name]
383
+ if !outbound_relationships[predicate].nil?
384
+ outbound_relationships[predicate].each do |rel|
385
+ id_array << rel.gsub("info:fedora/", "")
386
+ end
387
+ end
388
+ query = self.class.outbound_relationship_query(relationship_name,id_array)
389
+ elsif inbound_relationship_names.include?(relationship_name)
390
+ query = self.class.inbound_relationship_query(pid,relationship_name)
391
+ end
392
+ query
393
+ end
394
+
395
+ ## Deprecated method checks for HYDRA-541 methods renamed
396
+ #
397
+ # Old Name New Name
398
+ # named_relationship find_relationship_by_name
399
+ # register_named_subject register_relationship_desc_subject
400
+ # register_named_relationship register_relationship_desc
401
+ # named_relationships relationships_by_name
402
+ # named_relationships_from_class relationships_by_name_from_class
403
+ # named_inbound_relationships inbound_relationship_names
404
+ # outbound_named_relationship_predicates outbound_relationship_predicates
405
+ # inbound_named_relationship_predicates inbound_relationship_predicates
406
+ # named_relationship_predicates relationship_predicates
407
+ # named_relationship_predicates_from_class relationship_predicates_from_class
408
+ # named_outbound_relationships outbound_relationships_by_name
409
+ # is_named_relationship? is_relationship_name?
410
+ # named_relationships_desc relationships_desc
411
+ # named_relationships_desc_from_class relationships_desc_from_class
412
+ # named_relationship_type relationship_model_type
413
+ # add_named_relationship add_relationship_by_name
414
+ # remove_named_relationship remove_relationship_by_name
415
+ # assert_kind_of_model assert_conforms_to
416
+ # kind_of_model? conforms_to?
417
+ # named_relationship_query relationship_query
418
+ # CLASS METHODS
419
+ # named_relationships_desc relationships_desc
420
+ # register_named_subject register_relationship_desc_subject
421
+ # register_named_relationship register_relationship_desc
422
+ # create_named_relationship_method create_relationship_name_methods
423
+ # create_bidirectional_named_relationship_methods create_bidirectional_relationship_name_methods
424
+ # outbound_named_relationship_query outbound_relationship_query
425
+ # inbound_named_relationship_query inbound_relationship_query
426
+ # bidirectional_named_relationship_query bidirectional_relationship_query
427
+ # named_predicate_exists_with_different_name? predicate_exists_with_different_relationship_name?
428
+
429
+ # @deprecated Please use {#find_relationship_by_name} instead.
430
+ def named_relationship(name)
431
+ logger.warn("Deprecation: named_relationship has been deprecated. Please call find_relationship_by_name instead.")
432
+ find_relationship_by_name(name)
433
+ end
434
+
435
+ # @deprecated Please use {#register_relationship_desc_subject} instead.
436
+ def register_named_subject(subject)
437
+ logger.warn("Deprecation: register_named_subject has been deprecated. Please call register_relationship_desc_subject instead.")
438
+ register_relationship_desc_subject(subject)
439
+ end
440
+
441
+ # @deprecated Please use {#register_relationship_desc} instead.
442
+ def register_named_relationship(subject, name, predicate, opts)
443
+ logger.warn("Deprecation: register_named_relationship has been deprecated. Please call register_relationship_desc instead.")
444
+ register_relationship_desc(subject, name, predicate, opts)
445
+ end
446
+
447
+ # @deprecated Please use {#relationships_by_name} instead.
448
+ def named_relationships(outbound_only=true)
449
+ logger.warn("Deprecation: named_relationships has been deprecated. Please call relationships_by_name instead.")
450
+ relationships_by_name(outbound_only)
451
+ end
452
+
453
+ # @deprecated Please use {#relationships_by_name_from_class} instead.
454
+ def named_relationships_from_class
455
+ logger.warn("Deprecation: named_relationships_from_class has been deprecated. Please call relationships_by_name_from_class instead.")
456
+ relationships_by_name_from_class
457
+ end
458
+
459
+ # @deprecated Please use {#inbound_relationships_by_name} instead.
460
+ def named_inbound_relationships
461
+ logger.warn("Deprecation: named_inbound_relationships has been deprecated. Please call inbound_relationships_by_name instead.")
462
+ inbound_relationships_by_name
463
+ end
464
+
465
+ # @deprecated Please use {#outbound_relationships_by_name} instead.
466
+ def named_outbound_relationships
467
+ logger.warn("Deprecation: named_outbound_relationships has been deprecated. Please call outbound_relationships_by_name instead.")
468
+ outbound_relationships_by_name
469
+ end
470
+
471
+ # @deprecated Please use {#outbound_relationship_predicates} instead.
472
+ def outbound_named_relationship_predicates
473
+ logger.warn("Deprecation: outbound_named_relationship_predicates has been deprecated. Please call outbound_relationship_predicates instead.")
474
+ outbound_relationship_predicates
475
+ end
476
+
477
+ # @deprecated Please use {#inbound_relationship_predicates} instead.
478
+ def inbound_named_relationship_predicates
479
+ logger.warn("Deprecation: inbound_named_relationship_predicates has been deprecated. Please call inbound_relationship_predicates instead.")
480
+ inbound_relationship_predicates
481
+ end
482
+
483
+ # @deprecated Please use {#relationship_predicates} instead.
484
+ def named_relationship_predicates
485
+ logger.warn("Deprecation: named_relationship_predicates has been deprecated. Please call relationship_predicates instead.")
486
+ relationship_predicates
487
+ end
488
+
489
+ # @deprecated Please use {#relationship_predicates_from_class} instead.
490
+ def named_relationship_predicates_from_class
491
+ logger.warn("Deprecation: named_relationship_predicates_from_class has been deprecated. Please call relationship_predicates_from_class instead.")
492
+ relationship_predicates_from_class
493
+ end
494
+
495
+ # @deprecated Please use {#is_relationship_name?} instead.
496
+ def is_named_relationship?(name, outbound_only=true)
497
+ logger.warn("Deprecation: is_named_relationship? has been deprecated. Please call is_relationship_name? instead.")
498
+ is_relationship_name?(name,outbound_only)
499
+ end
500
+
501
+ # @deprecated Please use {#relationships_desc} instead.
502
+ def named_relationships_desc
503
+ logger.warn("Deprecation: named_relationships_desc has been deprecated. Please call relationships_desc instead.")
504
+ relationships_desc
505
+ end
506
+
507
+ # @deprecated Please use {#relationships_desc_from_class} instead.
508
+ def named_relationships_desc_from_class
509
+ logger.warn("Deprecation: named_relationships_desc_from_class has been deprecated. Please call relationships_desc_from_class instead.")
510
+ relationships_desc_from_class
511
+ end
512
+
513
+ # @deprecated Please use {#relationship_model_type} instead.
514
+ def named_relationship_type(name)
515
+ logger.warn("Deprecation: named_relationship_type has been deprecated. Please call relationship_model_type instead.")
516
+ relationship_model_type(name)
517
+ end
518
+
519
+ # @deprecated Please use {#add_relationship_by_name} instead.
520
+ def add_named_relationship(name,object)
521
+ logger.warn("Deprecation: add_named_relationship has been deprecated. Please call add_relationship_by_name instead.")
522
+ add_relationship_by_name(name,object)
523
+ end
524
+
525
+ # @deprecated Please use {#remove_relationship_by_name} instead.
526
+ def remove_named_relationship(name,object)
527
+ logger.warn("Deprecation: remove_named_relationship has been deprecated. Please call remove_relationship_by_name instead.")
528
+ remove_relationship_by_name(name,object)
529
+ end
530
+
531
+ # @deprecated Please use {#assert_conforms_to} instead.
532
+ def assert_kind_of_model(name,object,model_class)
533
+ logger.warn("Deprecation: assert_kind_of_model has been deprecated. Please call assert_conforms_to instead.")
534
+ assert_conforms_to(name,object,model_class)
535
+ end
536
+
537
+ # @deprecated Please use {#conforms_to?} instead.
538
+ def kind_of_model?(model_class)
539
+ logger.warn("Deprecation: kind_of_model? has been deprecated. Please call conforms_to? instead.")
540
+ conforms_to?(model_class)
541
+ end
542
+
543
+ # @deprecated Please use {#relationship_query} instead.
544
+ def named_relationship_query(relationship_name)
545
+ logger.warn("Deprecation: named_relationship_query has been deprecated. Please call relationship_query instead.")
546
+ relationship_query(relationship_name)
547
+ end
548
+
549
+ module ClassMethods
550
+
551
+ # ** EXPERIMENTAL **
552
+ #
553
+ # Return hash that persists relationship metadata defined by has_relationship calls. If you implement a child class of ActiveFedora::Base it will inherit
554
+ # the relationship descriptions defined there by merging in the class
555
+ # instance variable values. It will also do this for any level of
556
+ # ancestors.
557
+ # @return [Hash] Hash of relationship subject (:self or :inbound) mapped to nested hashs of each relationship name mapped to another hash relationship options
558
+ # @example
559
+ # For the following relationship
560
+ #
561
+ # has_relationship "audio_records", :has_part, :type=>AudioRecord
562
+ #
563
+ # Results in the following returned by relationships_desc
564
+ # {:self=>{"audio_records"=>{:type=>AudioRecord, :singular=>nil, :predicate=>:has_part, :inbound=>false}}}
565
+ def relationships_desc
566
+ #get any relationship descriptions from superclasses
567
+ if @class_relationships_desc.nil?
568
+ @class_relationships_desc ||= Hash[:self => {}]
569
+
570
+ #get super classes
571
+ super_klasses = []
572
+ #insert in reverse order so the child overwrites anything in parent
573
+ super_klass = self.superclass
574
+ while !super_klass.nil?
575
+ super_klasses.insert(0,super_klass)
576
+ super_klass = super_klass.superclass
577
+ end
578
+
579
+ super_klasses.each do |super_klass|
580
+ if super_klass.respond_to?(:relationships_desc)
581
+ super_rels = super_klass.relationships_desc
582
+ super_rels.each_pair do |subject,rels|
583
+ @class_relationships_desc[subject] = {} unless @class_relationships_desc.has_key?(subject)
584
+ @class_relationships_desc[subject].merge!(rels)
585
+ end
586
+ end
587
+ end
588
+ end
589
+ @class_relationships_desc
590
+ end
591
+
592
+ # ** EXPERIMENTAL **
593
+ #
594
+ # Internal method that ensures a relationship subject such as :self and :inbound
595
+ # exist within the relationships_desc hash tracking relationships metadata.
596
+ # @param [Symbol] Subject name to register (will probably be something like :self or :inbound)
597
+ def register_relationship_desc_subject(subject)
598
+ unless relationships_desc.has_key?(subject)
599
+ relationships_desc[subject] = {}
600
+ end
601
+ end
602
+
603
+ # ** EXPERIMENTAL **
604
+ #
605
+ # Internal method that adds relationship name and predicate pair to either an outbound (:self)
606
+ # or inbound (:inbound) relationship types. Refer to ActiveFedora::SemanticNode.has_relationship for information on what metadata will be persisted.
607
+ # @param [Symbol] Subject name to register
608
+ # @param [String] Name of relationship being registered
609
+ # @param [Symbol] Fedora ontology predicate to use
610
+ # @param [Hash] Any options passed to has_relationship such as :type, :solr_fq, etc.
611
+ def register_relationship_desc(subject, name, predicate, opts={})
612
+ register_relationship_desc_subject(subject)
613
+ opts.merge!({:predicate=>predicate})
614
+ relationships_desc[subject][name] = opts
615
+ end
616
+
617
+ # Tests if the relationship name passed is in bidirectional
618
+ # @param [String] relationship name to test
619
+ # @return [Boolean]
620
+ def is_bidirectional_relationship?(relationship_name)
621
+ (relationships_desc.has_key?(:self)&&relationships_desc.has_key?(:inbound)&&relationships_desc[:self].has_key?("#{relationship_name}_outbound") && relationships_desc[:inbound].has_key?("#{relationship_name}_inbound"))
622
+ end
623
+
624
+ # ** EXPERIMENTAL **
625
+ #
626
+ # Used in has_relationship call to create dynamic helper methods to
627
+ # append and remove objects to and from a relationship
628
+ # @param [String] relationship name to create helper methods for
629
+ # @example
630
+ # For the following relationship
631
+ #
632
+ # has_relationship "audio_records", :has_part, :type=>AudioRecord
633
+ #
634
+ # Methods audio_records_append and audio_records_remove are created.
635
+ # Boths methods take an object that is kind_of? ActiveFedora::Base as a parameter
636
+ def create_relationship_name_methods(name)
637
+ append_method_name = "#{name.to_s.downcase}_append"
638
+ remove_method_name = "#{name.to_s.downcase}_remove"
639
+ self.send(:define_method,:"#{append_method_name}") {|object| add_relationship_by_name(name,object)}
640
+ self.send(:define_method,:"#{remove_method_name}") {|object| remove_relationship_by_name(name,object)}
641
+ end
642
+
643
+ # ** EXPERIMENTAL **
644
+ # Similar to +create_relationship_name_methods+ except it is used when an ActiveFedora::Base model class
645
+ # declares has_bidirectional_relationship. we are merely creating an alias for outbound portion of bidirectional
646
+ # @param [String] bidirectional relationship name
647
+ # @param [String] outbound relationship method name associated with the bidirectional relationship ([bidirectional_name]_outbound)
648
+ # @example
649
+ # has_bidirectional_relationship "members", :has_collection_member, :is_member_of_collection
650
+ #
651
+ # Method members_outbound_append and members_outbound_remove added
652
+ # This method will create members_append which does same thing as members_outbound_append
653
+ # and will create members_remove which does same thing as members_outbound_remove
654
+ def create_bidirectional_relationship_name_methods(name,outbound_name)
655
+ append_method_name = "#{name.to_s.downcase}_append"
656
+ remove_method_name = "#{name.to_s.downcase}_remove"
657
+ self.send(:define_method,:"#{append_method_name}") {|object| add_relationship_by_name(outbound_name,object)}
658
+ self.send(:define_method,:"#{remove_method_name}") {|object| remove_relationship_by_name(outbound_name,object)}
659
+ end
660
+
661
+ # Returns a solr query for retrieving objects specified in an outbound relationship.
662
+ # This method is mostly used by internal method calls.
663
+ # It utilizes any solr_fq value defined within a relationship to attach a query filter when
664
+ # querying solr on top of just the predicate being used.
665
+ # Because it is static it
666
+ # needs the pids defined within RELS-EXT for this relationship to be passed in.
667
+ # If you are calling this method directly to get the query you should use the
668
+ # ActiveFedora::SemanticNode.relationship_query instead or use the helper method
669
+ # [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
670
+ # method would only be called directly if you had something like an array of outbound pids
671
+ # already in something like a solr document for object that has these relationships.
672
+ # @param [String] The name of the relationship defined in the model
673
+ # @param [Array] An array of pids to include in the query
674
+ # @return [String]
675
+ # @example
676
+ # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
677
+ # #points to all parents linked via is_member_of
678
+ # has_relationship "parents", :is_member_of
679
+ # #returns only parents that have a level value set to "series"
680
+ # has_relationship "series_parents", :is_member_of, :solr_fq=>"level_t:series"
681
+ # end
682
+ # s = SampleAFObjRelationshipFilterQuery.new
683
+ # obj = ActiveFedora::Base.new
684
+ # s.series_parents_append(obj)
685
+ # s.series_parents_query
686
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
687
+ # SampleAFObjRelationshipFilterQuery.outbound_relationship_query("series_parents",["id:changeme:13020"])
688
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
689
+ def outbound_relationship_query(relationship_name,outbound_pids)
690
+ query = ActiveFedora::SolrService.construct_query_for_pids(outbound_pids)
691
+ subject = :self
692
+ if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
693
+ solr_fq = relationships_desc[subject][relationship_name][:solr_fq]
694
+ unless query.empty?
695
+ #substitute in the filter query for each pid so that it is applied to each in the query
696
+ query_parts = query.split(/OR/)
697
+ query = ""
698
+ query_parts.each_with_index do |query_part,index|
699
+ query_part.strip!
700
+ query << " OR " if index > 0
701
+ query << "(#{query_part} AND #{solr_fq})"
702
+ end
703
+ else
704
+ query = solr_fq
705
+ end
706
+ end
707
+ query
708
+ end
709
+
710
+ # Returns a solr query for retrieving objects specified in an inbound relationship.
711
+ # This method is mostly used by internal method calls.
712
+ # It utilizes any solr_fq value defined within a relationship to attach a query filter
713
+ # on top of just the predicate being used. Because it is static it
714
+ # needs the pid of the object that has the inbound relationships passed in.
715
+ # If you are calling this method directly to get the query you should use the
716
+ # ActiveFedora::SemanticNode.relationship_query instead or use the helper method
717
+ # [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
718
+ # method would only be called directly if you were working only with Solr and already
719
+ # had the pid for the object in something like a solr document.
720
+ # @param [String] The pid for the object that has these inbound relationships
721
+ # @param [String] The name of the relationship defined in the model
722
+ # @return [String]
723
+ # @example
724
+ # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
725
+ # #returns all parts
726
+ # has_relationship "parts", :is_part_of, :inbound=>true
727
+ # #returns only parts that have level to "series"
728
+ # has_relationship "series_parts", :is_part_of, :inbound=>true, :solr_fq=>"level_t:series"
729
+ # end
730
+ # s = SampleAFObjRelationshipFilterQuery.new
731
+ # s.pid
732
+ # #=> id:changeme:13020
733
+ # s.series_parts_query
734
+ # #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
735
+ # SampleAFObjRelationshipFilterQuery.inbound_relationship_query(s.pid,"series_parts")
736
+ # #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
737
+ def inbound_relationship_query(pid,relationship_name)
738
+ query = ""
739
+ subject = :inbound
740
+ if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name)
741
+ predicate = relationships_desc[subject][relationship_name][:predicate]
742
+ internal_uri = "info:fedora/#{pid}"
743
+ escaped_uri = internal_uri.gsub(/(:)/, '\\:')
744
+ query = "#{predicate}_s:#{escaped_uri}"
745
+ if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
746
+ solr_fq = relationships_desc[subject][relationship_name][:solr_fq]
747
+ query << " AND " unless query.empty?
748
+ query << solr_fq
749
+ end
750
+ end
751
+ query
752
+ end
753
+
754
+ # Returns a solr query for retrieving objects specified in a bidirectional relationship.
755
+ # This method is mostly used by internal method calls.
756
+ # It usea of solr_fq value defined within a relationship to attach a query filter
757
+ # on top of just the predicate being used. Because it is static it
758
+ # needs the pids defined within RELS-EXT for the outbound relationship as well as the pid of the
759
+ # object for the inbound portion of the relationship.
760
+ # If you are calling this method directly to get the query you should use the
761
+ # ActiveFedora::SemanticNode.relationship_query instead or use the helper method
762
+ # [relationship_name]_query, i.e. method "bi_parts_query" for relationship "bi_parts". This
763
+ # method would only be called directly if you had something like an array of outbound pids
764
+ # already in something like a solr document for object that has these relationships.
765
+ # @param [String] The pid for the object that has these inbound relationships
766
+ # @param [String] The name of the relationship defined in the model
767
+ # @param [Array] An array of pids to include in the query
768
+ # @return [String]
769
+ # @example
770
+ # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
771
+ # has_bidirectional_relationship "bi_series_parts", :has_part, :is_part_of, :solr_fq=>"level_t:series"
772
+ # end
773
+ # s = SampleAFObjRelationshipFilterQuery.new
774
+ # obj = ActiveFedora::Base.new
775
+ # s.bi_series_parts_append(obj)
776
+ # s.pid
777
+ # #=> "changeme:13025"
778
+ # obj.pid
779
+ # #=> id:changeme:13026
780
+ # s.bi_series_parts_query
781
+ # #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
782
+ # SampleAFObjRelationshipFilterQuery.bidirectional_relationship_query(s.pid,"series_parents",["id:changeme:13026"])
783
+ # #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
784
+ def bidirectional_relationship_query(pid,relationship_name,outbound_pids)
785
+ outbound_query = outbound_relationship_query("#{relationship_name}_outbound",outbound_pids)
786
+ inbound_query = inbound_relationship_query(pid,"#{relationship_name}_inbound")
787
+ query = outbound_query # use outbound_query by default
788
+ if !inbound_query.empty?
789
+ query << " OR (" + inbound_relationship_query(pid,"#{relationship_name}_inbound") + ")"
790
+ end
791
+ return query
792
+ end
793
+
794
+ # Check if a relationship has any solr query filters defined by has_relationship call
795
+ # @param [Symbol] subject to use such as :self or :inbound
796
+ # @param [String] relationship name
797
+ # @return [Boolean] true if the relationship has a query filter defined
798
+ def relationship_has_solr_filter_query?(subject, relationship_name)
799
+ relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
800
+ end
801
+
802
+ # ** EXPERIMENTAL **
803
+ #
804
+ # Check to make sure a subject,name, and predicate triple does not already exist
805
+ # with the same subject but different name.
806
+ # This method is used to ensure conflicting has_relationship calls are not made because
807
+ # predicates cannot be reused across relationship names. Otherwise, the mapping of relationship name
808
+ # to predicate in RELS-EXT would be broken.
809
+ # @param [Symbol] subject to check (:self or :inbound)
810
+ # @param [String] relationship name
811
+ # @param [Symbol] symbol for Fedora relationship ontology predicate
812
+ def predicate_exists_with_different_relationship_name?(subject,name,predicate)
813
+ if relationships_desc.has_key?(subject)
814
+ relationships_desc[subject].each_pair do |existing_name, args|
815
+ return true if !args[:predicate].nil? && args[:predicate] == predicate && existing_name != name
816
+ end
817
+ end
818
+ return false
819
+ end
820
+
821
+ ## Deprecated class method checks for HYDRA-541 methods renamed
822
+ #
823
+ # Old Name New Name
824
+ # named_relationships_desc relationships_desc
825
+ # register_named_subject register_relationship_desc_subject
826
+ # register_named_relationship register_relationship_desc
827
+ # create_named_relationship_method create_relationship_name_methods
828
+ # create_bidirectional_named_relationship_methods create_bidirectional_relationship_name_methods
829
+ # outbound_named_relationship_query outbound_relationship_query
830
+ # inbound_named_relationship_query inbound_relationship_query
831
+ # bidirectional_named_relationship_query bidirectional_relationship_query
832
+ # named_predicate_exists_with_different_name? predicate_exists_with_different_relationship_name?
833
+
834
+ # @deprecated Please use {#relationships_desc} instead.
835
+ def named_relationships_desc
836
+ logger.warn("Deprecation: named_relationships_desc has been deprecated. Please call relationships_desc instead.")
837
+ relationships_desc
838
+ end
839
+
840
+ # @deprecated Please use {#register_relationship_desc_subject} instead.
841
+ def register_named_subject(subject)
842
+ logger.warn("Deprecation: register_named_subject has been deprecated. Please call register_relationship_desc_subject instead.")
843
+ register_relationship_desc_subject(subject)
844
+ end
845
+
846
+ # @deprecated Please use {#register_relationship_desc} instead.
847
+ def register_named_relationship(subject, name, predicate, opts)
848
+ logger.warn("Deprecation: register_named_relationship has been deprecated. Please call register_relationship_desc instead.")
849
+ register_relationship_desc(subject, name, predicate, opts)
850
+ end
851
+
852
+ # @deprecated Please use {#create_relationship_name_methods} instead.
853
+ def create_named_relationship_methods(name)
854
+ logger.warn("Deprecation: create_named_relationship_methods has been deprecated. Please call create_relationship_name_methods instead.")
855
+ create_relationship_name_methods(name)
856
+ end
857
+
858
+ # @deprecated Please use {#create_bidirectional_relationship_name_methods} instead.
859
+ def create_bidirectional_named_relationship_methods(name,outbound_name)
860
+ logger.warn("Deprecation: create_bidirectional_named_relationship_methods has been deprecated. Please call create_bidirectional_relationship_name_methods instead.")
861
+ create_bidirectional_relationship_name_methods(name,outbound_name)
862
+ end
863
+
864
+ # @deprecated Please use {#outbound_relationship_query} instead.
865
+ def outbound_named_relationship_query(relationship_name,outbound_pids)
866
+ logger.warn("Deprecation: outbound_named_relationship_query has been deprecated. Please call outbound_relationship_query instead.")
867
+ outbound_relationship_query(relationship_name,outbound_pids)
868
+ end
869
+
870
+ # @deprecated Please use {#inbound_relationship_query} instead.
871
+ def inbound_named_relationship_query(pid,relationship_name)
872
+ logger.warn("Deprecation: inbound_named_relationship_query has been deprecated. Please call inbound_relationship_query instead.")
873
+ inbound_relationship_query(pid,relationship_name)
874
+ end
875
+
876
+ # @deprecated Please use {#bidirectional_relationship_query} instead.
877
+ def bidirectional_named_relationship_query(pid,relationship_name,outbound_pids)
878
+ logger.warn("Deprecation: bidirectional_named_relationship_query has been deprecated. Please call bidirectional_relationship_query instead.")
879
+ bidirectional_relationship_query(pid,relationship_name,outbound_pids)
880
+ end
881
+
882
+ # @deprecated Please use {#predicate_exists_with_different_relationship_name?} instead.
883
+ def named_predicate_exists_with_different_name?(subject,name,predicate)
884
+ logger.warn("Deprecation: named_predicate_exists_with_different_name? has been deprecated. Please call predicate_exists_with_different_relationship_name? instead.")
885
+ predicate_exists_with_different_relationship_name?(subject,name,predicate)
886
+ end
887
+ end
888
+ end
889
+ end