Class: ContainerItem
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- ContainerItem
- Includes:
- Housekeeping, Shared::IsData
- Defined in:
- app/models/container_item.rb
Overview
ContainerItem tells you where this item is contained in. Containers contain ContainerItems, not the objects themselves.
A container item is something that has been “localized to” a container.
We can’t say that it is “in” the container, because not all containers (e.g. a pin with three specimens) contain the object.
By “localized to” we mean that if you can find the container, then its contents should also be locatable.
This concept is a graph edge defining the relationship to the container.
The position coordinate system has (x,y,z) starting 0,0,0 in the top left, with Z moving “into” the screen.
Instance Attribute Summary collapse
-
#contained_object_id ⇒ Integer
The id of the object that is contained (Rails polymorphic).
-
#contained_object_type ⇒ String
The type of the object that is contained (Rails polymorphic).
-
#container_id ⇒ Object
Returns the value of attribute container_id.
-
#disposition_x ⇒ Integer
A x coordinate for this item in its container.
-
#disposition_y ⇒ Integer
A y coordinate for this item in its container, we use “top” y for zero.
-
#disposition_z ⇒ Integer
A z coordinate for this item in its container, we use “in” Z for zero.
-
#global_entity ⇒ GlobalID
TODO: this is silly, type should be the same.
-
#localization ⇒ String
some additional modifier arbitrarily defining the position of this item, aka disposition, always relative to enclosing container.
-
#parent_id ⇒ Integer
Id of the ContainerItem whose contained_object is a Container, i.e.
-
#project_id ⇒ Integers
the project ID.
Class Method Summary collapse
Instance Method Summary collapse
-
#contained_object_is_container_when_parent_id_is_blank ⇒ Object
protected
If the contained_object is a CollectionObject, it must have a parent container reference.
- #contained_object_is_unique ⇒ Object protected
-
#container ⇒ Container?
The immediate container for this ContainerItem.
- #container=(object) ⇒ Object
- #object_fits_in_container ⇒ Object protected
-
#parent_contained_object_is_container ⇒ Object
protected
parent_id links an object to a container through container_item.
- #parent_is_provided_if_object_is_not_container ⇒ Object protected
- #position_is_not_replicated ⇒ Object protected
- #set_container ⇒ Object protected
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 Housekeeping
#has_polymorphic_relationship?
Methods inherited from ApplicationRecord
Instance Attribute Details
#contained_object_id ⇒ Integer
Returns the id of the object that is contained (Rails polymorphic).
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#contained_object_type ⇒ String
Returns the type of the object that is contained (Rails polymorphic).
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#container_id ⇒ Object
Returns the value of attribute container_id.
63 64 65 |
# File 'app/models/container_item.rb', line 63 def container_id @container_id end |
#disposition_x ⇒ Integer
Returns a x coordinate for this item in its container.
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#disposition_y ⇒ Integer
Returns a y coordinate for this item in its container, we use “top” y for zero.
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#disposition_z ⇒ Integer
Returns a z coordinate for this item in its container, we use “in” Z for zero.
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#global_entity ⇒ GlobalID
TODO: this is silly, type should be the same
133 134 135 |
# File 'app/models/container_item.rb', line 133 def global_entity @global_entity end |
#localization ⇒ String
some additional modifier arbitrarily defining the position of this item, aka disposition, always relative to enclosing container
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#parent_id ⇒ Integer
Returns id of the ContainerItem whose contained_object is a Container, i.e. the container of this ContainerItem.
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
#project_id ⇒ Integers
the project ID
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 |
# File 'app/models/container_item.rb', line 45 class ContainerItem < ApplicationRecord # @return class # this method calls Module#module_parent # TODO: This method can be placed elsewhere inside this class (or even removed if not used) # when https://github.com/ClosureTree/closure_tree/issues/346 is fixed. # TODO: issue is closed, testing. # def self.parent # self.module_parent # end has_closure_tree include Housekeeping include Shared::IsData attr_accessor :global_entity attr_accessor :container_id belongs_to :contained_object, polymorphic: true, inverse_of: :container_item validates :contained_object, presence: true validate :parent_contained_object_is_container validate :contained_object_is_container_when_parent_id_is_blank validate :contained_object_is_unique validate :object_fits_in_container validate :position_is_not_replicated validate :parent_is_provided_if_object_is_not_container scope :containers, -> { where(contained_object_type: 'Container') } scope :not_containers, -> { where.not(contained_object_type: 'Container') } scope :containing_collection_objects, -> {where(contained_object_type: 'CollectionObject')} # @params object [Container] def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end # @param value [a Container#id] def container_id=(value) @container_id = value set_container end # @params def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end # @return [Container, nil] # the immediate container for this ContainerItem def container parent&.contained_object end # TODO: this is silly, type should be the same # @return [GlobalID] # ! not a string def global_entity contained_object.to_global_id if contained_object.present? end # @params entity [String, a global id] def global_entity=(entity) self.contained_object = GlobalID::Locator.locate(entity) end protected def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end # If the contained_object is a CollectionObject, it must have a parent container reference def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end # parent_id links an object to a container through container_item def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end end |
Class Method Details
.batch_add(params) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'app/models/container_item.rb', line 102 def self.batch_add(params) c = Container.find(params[:container_id]) q = Queries::Query::Filter.instantiated_base_filter(params) cit = c.container_items.count r = ::BatchResponse.new( total_attempted: q.all.count, async: false, preview: false, ) c.add_container_items(q.all) cia = c.container_items.reload.count r.updated = r.total_attempted - (cia - cit) r.not_updated = r.total_attempted - r.updated return r.to_json end |
Instance Method Details
#contained_object_is_container_when_parent_id_is_blank ⇒ Object (protected)
If the contained_object is a CollectionObject, it must have a parent container reference
187 188 189 190 191 |
# File 'app/models/container_item.rb', line 187 def contained_object_is_container_when_parent_id_is_blank if parent_id.blank? && container_id.blank? && container.blank? errors.add(:parent_id, 'can only be blank if object is a container') if contained_object_type != 'Container' end end |
#contained_object_is_unique ⇒ Object (protected)
206 207 208 209 210 |
# File 'app/models/container_item.rb', line 206 def contained_object_is_unique if ContainerItem.where.not(id: id).where(project_id: project_id, contained_object_id: contained_object_id, contained_object_type: contained_object_type).count > 0 errors.add(:contained_object, 'is already in a container_item') end end |
#container ⇒ Container?
Returns the immediate container for this ContainerItem.
126 127 128 |
# File 'app/models/container_item.rb', line 126 def container parent&.contained_object end |
#container=(object) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'app/models/container_item.rb', line 81 def container=(object) if object..kind_of?(Container) if self.parent self.parent.contained_object = object else # This self required?! self.parent = ContainerItem.new(contained_object: object) end self.parent.save! if !self.parent.new_record? save! unless new_record? end end |
#object_fits_in_container ⇒ Object (protected)
165 166 167 168 169 170 171 172 |
# File 'app/models/container_item.rb', line 165 def object_fits_in_container if parent %w{x y z}.each do |coord| c = send("disposition_#{coord}") errors.add("disposition_#{coord}".to_sym, 'is larger than the container size') if c && parent.contained_object.send("size_#{coord}") < c end end end |
#parent_contained_object_is_container ⇒ Object (protected)
parent_id links an object to a container through container_item
194 195 196 197 198 |
# File 'app/models/container_item.rb', line 194 def parent_contained_object_is_container unless parent_id.blank? && parent.nil? errors.add(:parent_id, "can only be set if parent's contained object is a container") if parent.contained_object_type != 'Container' end end |
#parent_is_provided_if_object_is_not_container ⇒ Object (protected)
200 201 202 203 204 |
# File 'app/models/container_item.rb', line 200 def parent_is_provided_if_object_is_not_container if !(contained_object_type =~ /Container/) && !parent errors.add(:parent, "must be set if contained object is not a container") end end |
#position_is_not_replicated ⇒ Object (protected)
174 175 176 177 178 179 180 181 182 183 184 |
# File 'app/models/container_item.rb', line 174 def position_is_not_replicated if parent && (disposition_x || disposition_y || disposition_z) if ContainerItem.where.not(id: id). where(parent: parent, disposition_x: disposition_x, disposition_y: disposition_y, disposition_z: disposition_z ).count > 0 errors.add(:base, 'position is already taken in this container') end end end |
#set_container ⇒ Object (protected)
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'app/models/container_item.rb', line 144 def set_container c = Container.find(container_id) # Already in some container if parent && parent.persisted? self.parent.update_columns(contained_object_type: 'Container', contained_object_id: c.id) # Not in container else # In same container as something else if d = c.container_item self.parent = d # In a new container else self.parent = ContainerItem.create!(contained_object: c) end end # self.parent.save! if !self.parent.new_record? # save! unless new_record? end |