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)
    end
  end

  result && self
end

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

Yields:

  • (record)


168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/active_fedora/associations/association_collection.rb', line 168

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

#create(attrs = {}) ⇒ Object



101
102
103
104
105
106
107
108
109
110
# File 'lib/active_fedora/associations/association_collection.rb', line 101

def create(attrs = {})
  if attrs.is_a?(Array)
    attrs.collect { |attr| create(attr) }
  else
    create_record(attrs) do |record|
      yield(record) if block_given?
      record.save
    end
  end
end

#create!(attrs = {}) ⇒ Object



112
113
114
115
116
117
# File 'lib/active_fedora/associations/association_collection.rb', line 112

def create!(attrs = {})
  create_record(attrs) do |record|
    yield(record) if block_given?
    record.save!
  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



150
151
152
153
154
155
156
157
158
159
160
# File 'lib/active_fedora/associations/association_collection.rb', line 150

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

  # Set the default classname to base inheritance on.
  opts = {}
  opts[:class] = @reflection.class_name.constantize.to_class_uri unless @reflection.class_name.nil?

#TODO, don't reify, just store the solr results and lazily reify.
  return ActiveFedora::SolrService.reify_solr_results(solr_result)
end

#load_from_solrObject



162
163
164
165
# File 'lib/active_fedora/associations/association_collection.rb', line 162

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

#load_targetObject



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/active_fedora/associations/association_collection.rb', line 120

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 => e
      ActiveFedora::Base.logger.error "Solr and Fedora may be out of sync:\n" + e.message
      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