Class: ActiveFedora::Associations::AssociationCollection

Inherits:
AssociationProxy show all
Defined in:
lib/active_fedora/associations/association_collection.rb

Overview

:nodoc:

Instance Method Summary collapse

Methods inherited from AssociationProxy

#loaded, #loaded?, #reload, #target, #target=

Constructor Details

#initialize(owner, reflection) ⇒ AssociationCollection

Returns a new instance of AssociationCollection.



4
5
6
7
# File 'lib/active_fedora/associations/association_collection.rb', line 4

def initialize(owner, reflection)
  super
  construct_query
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class ActiveFedora::Associations::AssociationProxy

Instance Method Details

#<<(*records) ⇒ Object Also known as: push, concat

Add records to this association. Returns self so method calls may be chained. Since << flattens its argument list and inserts each record, push and concat behave identically.



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/active_fedora/associations/association_collection.rb', line 70

def <<(*records)
  result = true
  load_target unless loaded?

  flatten_deeper(records).each do |record|
    raise_on_type_mismatch(record)
    add_record_to_target_with_callbacks(record) do |r|
      result &&= insert_record(record) unless @owner.new_record?
    end
  end

  result && self
end

#add_record_to_target_with_callbacks(record) {|record| ... } ⇒ Object

Yields:

  • (record)


144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/active_fedora/associations/association_collection.rb', line 144

def add_record_to_target_with_callbacks(record)
#  callback(:before_add, record)
  yield(record) if block_given?
  @target ||= [] unless loaded?
  if index = @target.index(record)
    @target[index] = record
  else
     @target << record
  end
#  callback(:after_add, record)
#  set_inverse_instance(record, @owner)
  record
end

#build(attributes = {}, &block) ⇒ Object



57
58
59
60
61
62
63
64
65
66
# File 'lib/active_fedora/associations/association_collection.rb', line 57

def build(attributes = {}, &block)
  if attributes.is_a?(Array)
    attributes.collect { |attr| build(attr, &block) }
  else
    build_record(attributes) do |record|
      block.call(record) if block_given?
      set_belongs_to_association_for(record)
    end
  end
end

#delete(*records) ⇒ Object

Removes records from this association calling before_remove and after_remove callbacks.

This method is abstract in the sense that delete_records has to be provided by descendants. Note this method does not imply the records are actually removed from the database, that depends precisely on delete_records. They are in any case removed from the collection.



94
95
96
97
98
99
# File 'lib/active_fedora/associations/association_collection.rb', line 94

def delete(*records)
  remove_records(records) do |_records, old_records|
    delete_records(old_records) if old_records.any?
    _records.each { |record| @target.delete(record) }
  end
end

#find_targetObject



131
132
133
134
135
136
# File 'lib/active_fedora/associations/association_collection.rb', line 131

def find_target
  return [] if @finder_query.empty?
  solr_result = SolrService.query(@finder_query, :rows=>1000)
#TODO, don't reify, just store the solr results and lazily reify.
  return ActiveFedora::SolrService.reify_solr_results(solr_result)
end

#load_from_solrObject



138
139
140
141
# File 'lib/active_fedora/associations/association_collection.rb', line 138

def load_from_solr
  return [] if @finder_query.empty?
  SolrService.query(@finder_query, :rows=>1000)
end

#load_targetObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/active_fedora/associations/association_collection.rb', line 102

def load_target
  if !@owner.new_record?
    begin
      if !loaded?
        if @target.is_a?(Array) && @target.any?
          @target = find_target.map do |f|
            i = @target.index(f)
            if i
              @target.delete_at(i).tap do |t|
                keys = ["id"] + t.changes.keys + (f.attribute_names - t.attribute_names)
                t.attributes = f.attributes.except(*keys)
              end
            else
              f
            end
          end + @target
        else
          @target = find_target
        end
      end
    rescue ObjectNotFoundError
      reset
    end
  end

  loaded if target
  target
end

#replace(other_array) ⇒ Object

Replace this collection with other_array This will perform a diff and delete/add only records that have changed.



30
31
32
33
34
35
36
37
38
39
# File 'lib/active_fedora/associations/association_collection.rb', line 30

def replace(other_array)
  other_array.each { |val| raise_on_type_mismatch(val) }

  load_target
  other   = other_array.size < 100 ? other_array : other_array.to_set
  current = @target.size < 100 ? @target : @target.to_set

  delete(@target.select { |v| !other.include?(v) })
  concat(other_array.select { |v| !current.include?(v) })
end

#resetObject



52
53
54
55
# File 'lib/active_fedora/associations/association_collection.rb', line 52

def reset
  reset_target!
  @loaded = false
end

#sizeObject

Returns the size of the collection

If the collection has been already loaded size and length are equivalent. If not and you are going to need the records anyway length will take one less query. Otherwise size is more efficient.

This method is abstract in the sense that it relies on count_records, which is a method descendants have to provide.



17
18
19
20
21
22
23
24
25
26
# File 'lib/active_fedora/associations/association_collection.rb', line 17

def size
  if @owner.new_record? && @target
    @target.size
  elsif !loaded? && @target.is_a?(Array)
    unsaved_records = @target.select { |r| r.new_record? }
    unsaved_records.size + count_records
  else
    count_records
  end
end

#to_aryObject Also known as: to_a



42
43
44
45
46
47
48
49
# File 'lib/active_fedora/associations/association_collection.rb', line 42

def to_ary
  load_target
  if @target.is_a?(Array)
    @target.to_ary
  else
    Array.wrap(@target)
  end
end