Class: Formed::Associations::CollectionAssociation
- Inherits:
-
Association
- Object
- Association
- Formed::Associations::CollectionAssociation
- Defined in:
- lib/formed/associations/collection_association.rb
Overview
:nodoc:
Direct Known Subclasses
Instance Attribute Summary
Attributes inherited from Association
#disable_joins, #owner, #reflection, #target
Instance Method Summary collapse
- #add_to_target(record, skip_callbacks: false, replace: true, &block) ⇒ Object
- #build(attributes = nil, &block) ⇒ Object
-
#concat(*records) ⇒ Object
Add
records
to this association. -
#empty? ⇒ Boolean
Returns true if the collection is empty.
- #find_from_target? ⇒ Boolean
- #include?(record) ⇒ Boolean
- #load_target ⇒ Object
- #null_scope? ⇒ Boolean
-
#reader ⇒ Object
Implements the reader method, e.g.
-
#replace(other_array) ⇒ Object
Replace this collection with
other_array
. - #reset ⇒ Object
- #scope ⇒ Object
-
#size ⇒ Object
Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn’t been loaded, and calling
collection.size
if it has. - #target=(record) ⇒ Object
- #writer(records) ⇒ Object
Methods inherited from Association
#extensions, #initialize, #initialize_attributes, #klass, #loaded!, #loaded?, #marshal_dump, #marshal_load, #reload, #reset_negative_cache, #reset_scope, #set_inverse_instance, #stale_target?
Constructor Details
This class inherits a constructor from Formed::Associations::Association
Instance Method Details
#add_to_target(record, skip_callbacks: false, replace: true, &block) ⇒ Object
125 126 127 |
# File 'lib/formed/associations/collection_association.rb', line 125 def add_to_target(record, skip_callbacks: false, replace: true, &block) replace_on_target(record, skip_callbacks, replace: replace, &block) end |
#build(attributes = nil, &block) ⇒ Object
27 28 29 30 31 32 33 |
# File 'lib/formed/associations/collection_association.rb', line 27 def build(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| build(attr, &block) } else add_to_target(build_record(attributes, &block), replace: true) end end |
#concat(*records) ⇒ Object
Add records
to this association. Since << flattens its argument list and inserts each record, push
and concat
behave identically.
37 38 39 40 41 |
# File 'lib/formed/associations/collection_association.rb', line 37 def concat(*records) records = records.flatten load_target if owner.new_record? concat_records(records) end |
#empty? ⇒ Boolean
Returns true if the collection is empty.
If the collection has been loaded it is equivalent to collection.size.zero?
. If the collection has not been loaded, it is equivalent to !collection.exists?
. If the collection has not already been loaded and you are going to fetch the records anyway it is better to check collection.length.zero?
.
74 75 76 77 78 79 80 |
# File 'lib/formed/associations/collection_association.rb', line 74 def empty? if loaded? || @association_ids || reflection.has_cached_counter? size.zero? else target.empty? && !scope.exists? end end |
#find_from_target? ⇒ Boolean
149 150 151 152 153 154 155 |
# File 'lib/formed/associations/collection_association.rb', line 149 def find_from_target? loaded? || owner.strict_loading? || reflection.strict_loading? || owner.new_record? || target.any? { |record| record.new_record? || record.changed? } end |
#include?(record) ⇒ Boolean
106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/formed/associations/collection_association.rb', line 106 def include?(record) if record.is_a?(reflection.klass) if record.new_record? include_in_memory?(record) else loaded? ? target.include?(record) : scope.exists?(record.id) end else false end end |
#load_target ⇒ Object
118 119 120 121 122 123 |
# File 'lib/formed/associations/collection_association.rb', line 118 def load_target @target = merge_target_lists(find_target, target) if find_target? loaded! target end |
#null_scope? ⇒ Boolean
145 146 147 |
# File 'lib/formed/associations/collection_association.rb', line 145 def null_scope? owner.new_record? end |
#reader ⇒ Object
Implements the reader method, e.g. foo.items for Foo.has_many :items
7 8 9 10 11 12 13 14 |
# File 'lib/formed/associations/collection_association.rb', line 7 def reader ensure_klass_exists! reload if stale_target? @proxy ||= CollectionProxy.create(klass, self) @proxy.reset_scope end |
#replace(other_array) ⇒ Object
Replace this collection with other_array
. This will perform a diff and delete/add only records that have changed.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/formed/associations/collection_association.rb', line 84 def replace(other_array) other_array = other_array.map do |other| if other.class < Formed::Base other else build_record(other) end end original_target = load_target.dup if owner.new_record? replace_records(other_array, original_target) else replace_common_records_in_memory(other_array, original_target) if other_array != original_target transaction { replace_records(other_array, original_target) } else other_array end end end |
#reset ⇒ Object
20 21 22 23 24 25 |
# File 'lib/formed/associations/collection_association.rb', line 20 def reset super @target = [] @replaced_or_added_targets = Set.new @association_ids = nil end |
#scope ⇒ Object
142 143 |
# File 'lib/formed/associations/collection_association.rb', line 142 def scope end |
#size ⇒ Object
Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn’t been loaded, and calling collection.size
if it has.
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.
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/formed/associations/collection_association.rb', line 53 def size if !find_target? || loaded? target.size elsif @association_ids @association_ids.size elsif !association_scope.group_values.empty? load_target.size else unsaved_records = target.select(&:new_record?) unsaved_records.size + count_records end end |
#target=(record) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/formed/associations/collection_association.rb', line 129 def target=(record) return super unless reflection.klass.has_many_inversing case record when nil # It's not possible to remove the record from the inverse association. when Array super else replace_on_target(record, true, replace: true, inversing: true) end end |
#writer(records) ⇒ Object
16 17 18 |
# File 'lib/formed/associations/collection_association.rb', line 16 def writer(records) replace(records) end |