Module: ActiveFedora::Relationships

Extended by:
ActiveSupport::Concern
Defined in:
lib/active_fedora/relationships.rb

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#add_relationship_by_name(name, object) ⇒ Boolean

Add an outbound relationship for given relationship name See ActiveFedora::SemanticNode::ClassMethods.has_relationship

Parameters:

  • Name (String)

    of relationship

  • object (ActiveFedora::Base)

    to add to the relationship (expects ActvieFedora::Base to be an ancestor)

Returns:

  • (Boolean)

    returns true if add operation successful



239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/active_fedora/relationships.rb', line 239

def add_relationship_by_name(name, object)
  if is_relationship_name?(name,true)
    if relationships_desc[:self][name].has_key?(:type)
      klass = class_from_name(relationships_desc[:self][name][:type])
      unless klass.nil?
        (assert_conforms_to 'object', object, klass)
      end
    end
    add_relationship(outbound_relationship_predicates[name],object)
  else
    false
  end
end

#assert_conforms_to(name, object, model_class) ⇒ Object

Throws an assertion error if conforms_to? returns false for object and model_class

Parameters:

  • Name (String)

    of object (just label for output)

  • Expects (ActiveFedora::Base)

    to be an object that has ActiveFedora::Base as an ancestor of its class

  • The (Class)

    model class used in conforms_to? check on object



126
127
128
# File 'lib/active_fedora/relationships.rb', line 126

def assert_conforms_to(name, object, model_class)
  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)
end

#class_from_name(name) ⇒ Class

Returns a Class symbol for the given string for the class name

Parameters:

  • the (String)

    class name as a string

Returns:

  • (Class)

    the class as a Class object



136
137
138
139
140
# File 'lib/active_fedora/relationships.rb', line 136

def class_from_name(name)
  klass = name.to_s.split('::').inject(Kernel) {|scope, const_name| 
  scope.const_get(const_name)}
  (!klass.nil? && klass.is_a?(::Class)) ? klass : nil
end

#find_relationship_by_name(name) ⇒ Array

Return array of objects for a given relationship name

Parameters:

  • Name (String)

    of relationship to find

Returns:

  • (Array)

    Returns array of objects linked via the relationship name given



9
10
11
12
13
14
15
16
17
18
# File 'lib/active_fedora/relationships.rb', line 9

def find_relationship_by_name(name)
  rels = nil
  if inbound_relationship_names.include?(name)
    rels = relationships_by_name(false)[:inbound][name]
  elsif outbound_relationship_names.include?(name)
    rels = relationships_by_name[:self][name]
  end
  rels = [] if rels.nil?
  return rels
end

#inbound_relationship_namesArray

Return array of relationship names for all inbound relationships (coming from other objects’ RELS-EXT and Solr)

Returns:

  • (Array)

    of inbound relationship names for relationships declared via has_relationship in the class



22
23
24
# File 'lib/active_fedora/relationships.rb', line 22

def inbound_relationship_names
    relationships_desc.has_key?(:inbound) ? relationships_desc[:inbound].keys : []
end

#inbound_relationships_by_nameHash

Return hash of relationships_by_name defined within other objects’ RELS-EXT It returns a hash of relationship name to arrays of objects. It requeries solr each time this method is called.

Returns:

  • (Hash)

    Return hash of each relationship name mapped to an Array of objects linked to this object via inbound relationships



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/active_fedora/relationships.rb', line 30

def inbound_relationships_by_name
  rels = {}
  if relationships_desc.has_key?(:inbound)&&!relationships_desc[:inbound].empty?()
    inbound_rels = inbound_relationships
  
    if relationship_predicates.has_key?(:inbound)
      relationship_predicates[:inbound].each do |name, predicate|
        rels[name] = inbound_rels.has_key?(predicate) ? inbound_rels[predicate] : []
      end
    end
  end
  return rels
end

#is_relationship_name?(name, outbound_only = true) ⇒ Boolean

Returns true if the given relationship name is a relationship

Parameters:

  • Name (String)

    of relationship

  • If (Boolean)

    false checks inbound relationships as well (defaults to true)

Returns:

  • (Boolean)


151
152
153
154
155
156
157
# File 'lib/active_fedora/relationships.rb', line 151

def is_relationship_name?(name, outbound_only=true)
  if outbound_only
    outbound_relationship_names.include?(name)
  else
    (outbound_relationship_names.include?(name)||inbound_relationship_names.include?(name))
  end
end

#load_bidirectional(name, inbound_method_name, outbound_method_name, opts) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/active_fedora/relationships.rb', line 185

def load_bidirectional(name, inbound_method_name, outbound_method_name, opts) 
    opts = {:rows=>25}.merge(opts)
    if opts[:response_format] == :solr || opts[:response_format] == :load_from_solr
      predicate = outbound_relationship_predicates["#{name}_outbound"]
      outbound_id_array = ids_for_outbound(predicate)
      query = self.class.bidirectional_relationship_query(self.pid,"#{name}",outbound_id_array)
      solr_result = SolrService.query(query, :rows=>opts[:rows])
      
      if opts[:response_format] == :solr
        return solr_result
      elsif opts[:response_format] == :load_from_solr || self.load_from_solr
        return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
      else
        return ActiveFedora::SolrService.reify_solr_results(solr_result)
      end
    else
      ary = send(inbound_method_name,opts) + send(outbound_method_name, opts)
      return ary.uniq
    end
end

#load_inbound_relationship(name, predicate, opts = {}) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/active_fedora/relationships.rb', line 160

def load_inbound_relationship(name, predicate, opts={})
  opts = {:rows=>25}.merge(opts)
  query = self.class.inbound_relationship_query(self.pid,"#{name}")
  return [] if query.empty?
  if opts[:response_format] == :solr
    solr_result = SolrService.query query, :raw=>true, :rows=>opts[:rows]
    return solr_result
  else
    solr_result = SolrService.query(query, :rows=>opts[:rows]) 
    if opts[:response_format] == :id_array
      id_array = []
      solr_result.each do |hit|
        id_array << hit[SOLR_DOCUMENT_ID]
      end
      return id_array
    elsif opts[:response_format] == :load_from_solr || self.load_from_solr
      return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
    else
      return ActiveFedora::SolrService.reify_solr_results(solr_result)
    end
  end
end

#load_outbound_relationship(name, predicate, opts = {}) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/active_fedora/relationships.rb', line 206

def load_outbound_relationship(name, predicate, opts={})
  id_array = ids_for_outbound(predicate)
  if opts[:response_format] == :id_array  && !self.relationship_has_solr_filter_query?(:self,"#{name}")
    return id_array
  else
    query = self.class.outbound_relationship_query(name,id_array)
    solr_result = SolrService.query(query)
    if opts[:response_format] == :solr
      return solr_result
    elsif opts[:response_format] == :id_array
      return solr_result.map {|hit| hit[SOLR_DOCUMENT_ID] }
    elsif opts[:response_format] == :load_from_solr || self.load_from_solr
      return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
    else
      return ActiveFedora::SolrService.reify_solr_results(solr_result)
    end
  end
end

#outbound_relationship_namesArray

Return array of relationship names for all outbound relationships (coming from this object’s RELS-EXT)

Returns:

  • (Array)

    of outbound relationship names for relationships declared via has_relationship in the class



144
145
146
# File 'lib/active_fedora/relationships.rb', line 144

def outbound_relationship_names
    relationships_desc.has_key?(:self) ? relationships_desc[:self].keys : []
end

#relationship_has_solr_filter_query?(subject, relationship_name) ⇒ Boolean

Check if a relationship has any solr query filters defined by has_relationship call

Parameters:

  • subject (Symbol)

    to use such as :self or :inbound

  • relationship (String)

    name

Returns:

  • (Boolean)

    true if the relationship has a query filter defined



229
230
231
# File 'lib/active_fedora/relationships.rb', line 229

def relationship_has_solr_filter_query?(subject, relationship_name)
  relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
end

#relationship_query(relationship_name) ⇒ String

Call this method to return the query used against solr to retrieve any objects linked via the relationship name given.

Instead of this method you can also use the helper method [relationship_name]_query, i.e. method “parts_query” for relationship “parts” to return the same value

Examples:

Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
  #points to all parents linked via is_member_of
  has_relationship "parents", :is_member_of
  #returns only parents that have a level value set to "series"
  has_relationship "series_parents", :is_member_of, :solr_fq=>level_t:series"
end
s = SampleAFObjRelationshipFilterQuery.new
obj = ActiveFedora::Base.new
s.parents_append(obj)
s.series_parents_query 
#=> "(id:changeme\\:13020 AND level_t:series)" 
SampleAFObjRelationshipFilterQuery.relationship_query("series_parents")
#=> "(id:changeme\\:13020 AND level_t:series)" 

Parameters:

  • The (String)

    name of the relationship defined in the model

Returns:

  • (String)

    The query used when querying solr for objects for this relationship



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/active_fedora/relationships.rb', line 66

def relationship_query(relationship_name)
  query = ""
  if self.class.is_bidirectional_relationship?(relationship_name)
    predicate = outbound_relationship_predicates["#{relationship_name}_outbound"]
    id_array = ids_for_outbound(predicate)
    query = self.class.bidirectional_relationship_query(pid,relationship_name,id_array)
  elsif outbound_relationship_names.include?(relationship_name)
    predicate = outbound_relationship_predicates[relationship_name]
    id_array = ids_for_outbound(predicate)
    query = self.class.outbound_relationship_query(relationship_name,id_array)
  elsif inbound_relationship_names.include?(relationship_name)
    query = self.class.inbound_relationship_query(pid,relationship_name)
  end
  query
end

#relationships_by_name(outbound_only = true) ⇒ Hash

Gets the relationships hash with subject mapped to relationship names instead of relationship predicates (unlike the “relationships” method in SemanticNode) It has an optional parameter of outbound_only that defaults true. If false it will include inbound relationships in the results. Also, it will only reload outbound relationships if the relationships hash has changed since the last time this method was called.

Parameters:

  • if (Boolean)

    false it will include inbound relationships (defaults to true)

Returns:

  • (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



91
92
93
94
# File 'lib/active_fedora/relationships.rb', line 91

def relationships_by_name(outbound_only=true)
  @relationships_by_name = relationships_by_name_from_class()
  outbound_only ? @relationships_by_name : @relationships_by_name.merge(:inbound=>inbound_relationships_by_name)      
end

#relationships_by_name_from_classHash

Gets relationships by name from the class using the current relationships hash and relationship name,predicate pairs.

Returns:

  • (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



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/active_fedora/relationships.rb', line 99

def relationships_by_name_from_class()
  rels = {}
  relationship_predicates.each_pair do |subj, names|
    case subj
    when :self
      rels[:self] = {}
      names.each_pair do |name, predicate|
        set = []
        res = relationships.query(:predicate => Predicates.find_graph_predicate(predicate))
        res.each_object do |o|
          set << o.to_s
        end
        rels[:self][name] = set
      end
    when :inbound
      #nop
    end
  end
  return rels
end

#remove_relationship_by_name(name, object) ⇒ Boolean

Remove an object for the given relationship name

Parameters:

Returns:

  • (Boolean)

    return true if remove operation successful



257
258
259
260
261
262
263
# File 'lib/active_fedora/relationships.rb', line 257

def remove_relationship_by_name(name, object)
  if is_relationship_name?(name,true)
    remove_relationship(outbound_relationship_predicates[name],object)
  else
    return false
  end
end