Class: Container
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Container
- Includes:
- Housekeeping, Shared::Containable, Shared::Depictions, Shared::Identifiers, Shared::IsData, Shared::Labels, Shared::Loanable, Shared::Tags, SoftValidation
- Defined in:
- app/models/container.rb
Overview
A container localizes the proximity of one ore more physical things, at this point in the TW UI this is restricted to a number of collection objects.
Objects are placed in containers by reference to a ContainerItem.
Direct Known Subclasses
Aisle, Box, Building, Cabinet, Collection, Drawer, Envelope, Folder, Jar, PillBox, Pin, Room, Shelf, Site, Slide, SlideBox, UnitTray, Vial, VialRack, Virtual, WellPlate
Defined Under Namespace
Classes: Aisle, Box, Building, Cabinet, Collection, Drawer, Envelope, Folder, Jar, PillBox, Pin, Room, Shelf, Site, Slide, SlideBox, UnitTray, Vial, VialRack, Virtual, WellPlate
Constant Summary
Constants included from SoftValidation
SoftValidation::ANCESTORS_WITH_SOFT_VALIDATIONS
Instance Attribute Summary collapse
-
#disposition ⇒ String
A free text description of the position of this container.
-
#empty_container ⇒ Object
Returns the value of attribute empty_container.
-
#name ⇒ String
Abitrary name of this container.
-
#print_label ⇒ String
Text of a label to print for this container.
- #project_id ⇒ Integer
-
#size_x ⇒ Int
The number of slots in the x dimension.
-
#size_y ⇒ Int
The number of slots in the y dimension.
-
#size_z ⇒ Int
The number of slots in the z dimension.
-
#type ⇒ String
STI, the type of container.
Class Method Summary collapse
-
.class_name ⇒ String
The “common name” of this class.
-
.containerize(objects, klass = Container::Virtual) ⇒ Container
Places all objects in a new, parent-less container, saves it off, None of the objects are permitted to be new_records.
- .dimensions ⇒ Object
-
.valid_parents ⇒ Array of Strings
Valid containers class names that this container can fit in, by default none.
Instance Method Summary collapse
-
#add_container_items(objects) ⇒ Boolean
add the objects to this container.
-
#all_collection_object_ids ⇒ Array
Of CollectionObject#id of this container’s contents (recursive).
-
#all_contained_objects ⇒ Array
Return all #contained_object(s) (recursive).
-
#all_container_items ⇒ ContainerItem Scope
Return all ContainerItems contained in this container (recursive).
-
#available_space ⇒ Integer
The free space in this container (non-recursive).
- #check_for_contents ⇒ Object protected
-
#collection_object_ids ⇒ Array
Of CollectionObject#id of this container’s contents (no recursion).
-
#collection_objects ⇒ Array
Of CollectionObject#id of this container’s CollectionObjects only (with recursion).
-
#contained_objects ⇒ Array
Return all #contained_object(s) (non-recursive).
-
#container_items ⇒ ContainerItem Scope
TODO: fix Please call ‘reload_container_item` instead.
- #empty_contents ⇒ Object protected
-
#is_empty? ⇒ Boolean
Regardless whether size is defined, whether there is anything in this container (non-recursive).
-
#is_full? ⇒ Boolean
True if size is defined, and there is no space left in this container (non-recursive).
-
#is_nested? ⇒ Boolean
Whether this container is nested in other containers.
-
#size ⇒ Integer?
TODO: reserved word?.
- #type_is_valid ⇒ Object protected
Methods included from SoftValidation
#clear_soft_validations, #fix_for, #fix_soft_validations, #soft_fixed?, #soft_valid?, #soft_validate, #soft_validated?, #soft_validations, #soft_validators
Methods included from Shared::IsData
#errors_excepting, #full_error_messages_excepting, #identical, #is_community?, #is_destroyable?, #is_editable?, #is_in_use?, #is_in_users_projects?, #metamorphosize, #similar
Methods included from Shared::Tags
#reject_tags, #tag_with, #tagged?, #tagged_with?
Methods included from Shared::Loanable
#all_loan_items, #all_loans, #container_loan_items, #container_loaned?, #container_loans, #container_times_loaned, #current_loan, #current_loan_item, #has_been_loaned?, #is_loanable?, #loan_return_date, #loaned_in_container, #on_loan?, #times_loaned
Methods included from Shared::Labels
Methods included from Shared::Identifiers
#dwc_occurrence_id, #identified?, #next_by_identifier, #previous_by_identifier, #reject_identifiers, #uri, #uuid
Methods included from Shared::Depictions
#has_depictions?, #image_array=, #reject_depictions, #reject_images
Methods included from Shared::Containable
#contain, #containable?, #contained?, #contained_by?, #contained_siblings, #enclosing_containers, #put_in_container
Methods included from Housekeeping
#has_polymorphic_relationship?
Methods inherited from ApplicationRecord
Instance Attribute Details
#disposition ⇒ String
Returns a free text description of the position of this container.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#empty_container ⇒ Object
Returns the value of attribute empty_container.
38 39 40 |
# File 'app/models/container.rb', line 38 def empty_container @empty_container end |
#name ⇒ String
Returns abitrary name of this container.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#print_label ⇒ String
Returns text of a label to print for this container.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#project_id ⇒ Integer
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#size_x ⇒ Int
Returns the number of slots in the x dimension.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#size_y ⇒ Int
Returns the number of slots in the y dimension.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#size_z ⇒ Int
Returns the number of slots in the z dimension.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
#type ⇒ String
Returns STI, the type of container.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/container.rb', line 36 class Container < ApplicationRecord attr_accessor :empty_container include Housekeeping # !! Must come before Shared::Containable before_destroy :empty_contents, if: -> { empty_container } before_destroy :check_for_contents include Shared::Containable include Shared::Depictions include Shared::Identifiers include Shared::Labels include Shared::Loanable include Shared::Tags include Shared::IsData include SoftValidation has_many :collection_profiles, inverse_of: :container, dependent: :restrict_with_error validates :type, presence: true validate :type_is_valid # @return [ContainerItem Scope] # return all ContainerItems contained in this container (non recursive) # TODO: fix Please call `reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43) # def container_items container_item&.children || ContainerItem.none end # @return [ContainerItem Scope] # return all ContainerItems contained in this container (recursive) def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end # @return [Array] # return all #contained_object(s) (non-recursive) def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end # @return [Array] # return all #contained_object(s) (recursive) def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's CollectionObjects only (with recursion) def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end # @return [Array] of CollectionObject#id of this container's contents (no recursion) def collection_object_ids container_items.containing_collection_objects.pluck(:id) end # @return [Array] of CollectionObject#id of this container's contents (recursive) def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end # @return [Boolean] # regardless whether size is defined, whether there is anything in this container (non-recursive) def is_empty? !container_items.any? end # @return [Boolean] # whether this container is nested in other containers def is_nested? container_item && container_item.ancestors.any? end # @return [Boolean] # true if size is defined, and there is no space left in this container (non-recursive) def is_full? available_space == 0 end # @return [Integer] # the free space in this container (non-recursive) def available_space in_container = container_items.count if size size - in_container else nil end end # @return [Integer, nil] # the total number of "slots" or "spaces" this container has, it's size # TODO: reserved word? def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end # @return [String] # the "common name" of this class def self.class_name self.name.demodulize.underscore.humanize.downcase end # @return [Array of Strings] # valid containers class names that this container can fit in, by default none def self.valid_parents [] end def self.dimensions {} end # @return [Container] # places all objects in a new, parent-less container, saves it off, # None of the objects are permitted to be new_records. # !! If an object is in another container it is moved to the new container created here. def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end # @return [Boolean] # add the objects to this container def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end protected def empty_contents container_items.delete_all end def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end end |
Class Method Details
.class_name ⇒ String
Returns the “common name” of this class.
153 154 155 |
# File 'app/models/container.rb', line 153 def self.class_name self.name.demodulize.underscore.humanize.downcase end |
.containerize(objects, klass = Container::Virtual) ⇒ Container
Returns places all objects in a new, parent-less container, saves it off, None of the objects are permitted to be new_records. !! If an object is in another container it is moved to the new container created here.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'app/models/container.rb', line 171 def self.containerize(objects, klass = Container::Virtual) new_container = nil begin Container.transaction do new_container = klass.create() ci_parent = ContainerItem.create(contained_object: new_container) objects.each do |o| raise ActiveRecord::RecordInvalid if o.new_record? if o.container_item.nil? # contain an uncontained objet ContainerItem.create(parent: ci_parent, contained_object: o) else # move the object if it's in a container already o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end new_container end |
.dimensions ⇒ Object
163 164 165 |
# File 'app/models/container.rb', line 163 def self.dimensions {} end |
.valid_parents ⇒ Array of Strings
Returns valid containers class names that this container can fit in, by default none.
159 160 161 |
# File 'app/models/container.rb', line 159 def self.valid_parents [] end |
Instance Method Details
#add_container_items(objects) ⇒ Boolean
add the objects to this container
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'app/models/container.rb', line 195 def add_container_items(objects) return false if new_record? # TODO: Figure out why this reload is required. self.reload # this seems to be required under some (as yet undefined) circumstances. begin Container.transaction do ci_parent = container_item ci_parent ||= ContainerItem.create!(contained_object: self) objects.each do |o| return false if o.new_record? || !o.containable? # does this roll back transaction if o.container_item.nil? ContainerItem.create!(parent: ci_parent, contained_object: o) else # move the object to a new container # this triggers the closure_tree parenting/re-parenting o.container_item.update(parent_id: ci_parent.id) end end end rescue ActiveRecord::RecordInvalid return false end true end |
#all_collection_object_ids ⇒ Array
Returns of CollectionObject#id of this container’s contents (recursive).
99 100 101 102 |
# File 'app/models/container.rb', line 99 def all_collection_object_ids # all_container_items.containing_collection_objects.pluck(:id) collection_objects.map(&:id) end |
#all_contained_objects ⇒ Array
Return all #contained_object(s) (recursive)
83 84 85 86 |
# File 'app/models/container.rb', line 83 def all_contained_objects return [] if !reload_container_item container_item.descendants.map(&:contained_object) end |
#all_container_items ⇒ ContainerItem Scope
Return all ContainerItems contained in this container (recursive)
70 71 72 |
# File 'app/models/container.rb', line 70 def all_container_items reload_container_item.try(:descendants) || ContainerItem.none end |
#available_space ⇒ Integer
Returns the free space in this container (non-recursive).
124 125 126 127 128 129 130 131 |
# File 'app/models/container.rb', line 124 def available_space in_container = container_items.count if size size - in_container else nil end end |
#check_for_contents ⇒ Object (protected)
231 232 233 234 235 236 |
# File 'app/models/container.rb', line 231 def check_for_contents if !is_empty? errors.add(:base, 'is not empty, empty it before destroying it') throw :abort end end |
#collection_object_ids ⇒ Array
Returns of CollectionObject#id of this container’s contents (no recursion).
94 95 96 |
# File 'app/models/container.rb', line 94 def collection_object_ids container_items.containing_collection_objects.pluck(:id) end |
#collection_objects ⇒ Array
Returns of CollectionObject#id of this container’s CollectionObjects only (with recursion).
89 90 91 |
# File 'app/models/container.rb', line 89 def collection_objects all_container_items.containing_collection_objects.map(&:contained_object) end |
#contained_objects ⇒ Array
Return all #contained_object(s) (non-recursive)
76 77 78 79 |
# File 'app/models/container.rb', line 76 def contained_objects return [] if !reload_container_item container_item.children.map(&:contained_object) end |
#container_items ⇒ ContainerItem Scope
TODO: fix Please call ‘reload_container_item` instead. (called from container_items at /Users/jrflood/src/taxonworks/app/models/container.rb:43)
64 65 66 |
# File 'app/models/container.rb', line 64 def container_items container_item&.children || ContainerItem.none end |
#empty_contents ⇒ Object (protected)
223 224 225 |
# File 'app/models/container.rb', line 223 def empty_contents container_items.delete_all end |
#is_empty? ⇒ Boolean
Returns regardless whether size is defined, whether there is anything in this container (non-recursive).
106 107 108 |
# File 'app/models/container.rb', line 106 def is_empty? !container_items.any? end |
#is_full? ⇒ Boolean
Returns true if size is defined, and there is no space left in this container (non-recursive).
118 119 120 |
# File 'app/models/container.rb', line 118 def is_full? available_space == 0 end |
#is_nested? ⇒ Boolean
Returns whether this container is nested in other containers.
112 113 114 |
# File 'app/models/container.rb', line 112 def is_nested? container_item && container_item.ancestors.any? end |
#size ⇒ Integer?
TODO: reserved word?
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'app/models/container.rb', line 136 def size return nil if size_x.blank? && size_y.blank? && size_z.blank? if size_x if size_y if size_z size_x * size_y * size_z else size_x * size_y end else size_x end end end |
#type_is_valid ⇒ Object (protected)
227 228 229 |
# File 'app/models/container.rb', line 227 def type_is_valid raise ActiveRecord::SubclassNotFound, 'Invalid subclass' if type && !CONTAINER_TYPES.include?(type) end |