Class: ContainerItem
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- ContainerItem
- Includes:
- Housekeeping, Shared::IsData
- Defined in:
- app/models/container_item.rb
Overview
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.
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.
-
#disposition_z ⇒ Integer
A z coordinate for this item in its container.
-
#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.
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).
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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).
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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.
57 58 59 |
# File 'app/models/container_item.rb', line 57 def container_id @container_id end |
#disposition_x ⇒ Integer
Returns a x coordinate for this item in its container.
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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.
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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.
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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
107 108 109 |
# File 'app/models/container_item.rb', line 107 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
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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.
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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
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 |
# File 'app/models/container_item.rb', line 39 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 # !! this will prevent accepts_nested assignments if we add this validates_presence_of :contained_object_id 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')} # before_save :set_container, unless: Proc.new {|n| n.container_id.nil? || errors.any? } # @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 # @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 |
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
161 162 163 164 165 |
# File 'app/models/container_item.rb', line 161 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)
180 181 182 183 184 |
# File 'app/models/container_item.rb', line 180 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.
100 101 102 |
# File 'app/models/container_item.rb', line 100 def container parent&.contained_object end |
#container=(object) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'app/models/container_item.rb', line 78 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)
139 140 141 142 143 144 145 146 |
# File 'app/models/container_item.rb', line 139 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
168 169 170 171 172 |
# File 'app/models/container_item.rb', line 168 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)
174 175 176 177 178 |
# File 'app/models/container_item.rb', line 174 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)
148 149 150 151 152 153 154 155 156 157 158 |
# File 'app/models/container_item.rb', line 148 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)
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'app/models/container_item.rb', line 118 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 |