Class: BiologicalAssociation
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- BiologicalAssociation
- Includes:
- DwcExtensions, GlobiExtensions, Housekeeping, Shared::AssertedDistributions, Shared::AutoUuid, Shared::Citations, Shared::Confidences, Shared::DataAttributes, Shared::Depictions, Shared::Identifiers, Shared::IsData, Shared::Notes, Shared::QueryBatchUpdate, Shared::Tags, SoftValidation
- Defined in:
- app/models/biological_association.rb
Overview
A BiologicalAssociation defines a (biological) relationship between two entities. It is an edge in the graph of biological relationships. The relationship can be between two Otus, an Otu and a Collection Object, or between two Collection Objects. For example ‘Species Aus bus is the host_of individual A.’
Defined Under Namespace
Modules: DwcExtensions, GlobiExtensions
Constant Summary collapse
- GRAPH_ENTRY_POINTS =
[:asserted_distributions].freeze
Constants included from SoftValidation
SoftValidation::ANCESTORS_WITH_SOFT_VALIDATIONS
Instance Attribute Summary collapse
-
#biological_association_object_id ⇒ Integer
Rails polymorphic, id of the object.
-
#biological_association_object_type ⇒ String
Rails polymorphic, type of the object (e.g. CollectionObject).
-
#biological_association_subject_id ⇒ Integer
Rails polymorphic, id of the subject of the relationship.
-
#biological_association_subject_type ⇒ String
Rails polymorphic, type fo the subject (e.g. Otu).
-
#biological_relationship_id ⇒ Integer
The BiologicalRelationship id.
-
#object_global_id ⇒ Object
TODO: this is badly named.
-
#project_id ⇒ Integer
the project ID.
-
#rotate ⇒ Object
Returns the value of attribute rotate.
-
#subject_global_id ⇒ Object
Returns the value of attribute subject_global_id.
Class Method Summary collapse
- .batch_update(params) ⇒ Object
- .select_optimized(user_id, project_id, klass) ⇒ Object
- .set_batch_cap(request) ⇒ Object
-
.used_recently(user_id, project_id, used_on) ⇒ Scope
The max 10 most recently used.
Instance Method Summary collapse
- #association_is_unique ⇒ Object private
- #biological_association_object_type_is_allowed ⇒ Object private
- #biological_association_subject_type_is_allowed ⇒ Object private
- #dwc_extension_select ⇒ Object
-
#object ⇒ Object
!! You can not set with this method.
-
#object_class_name ⇒ Object
TODO: Why?! this is just biological_association.biological_association_object_type.
-
#subject ⇒ Object
!! You can not set with this method.
-
#subject_class_name ⇒ Object
TODO: Why?! this is just biological_association.biological_association_subject_type.
- #targeted_join(target: 'subject', target_class: ::Otu) ⇒ ActiveRecord::Relation
- #targeted_join2(target: 'subject', target_class: ::Otu) ⇒ ActiveRecord::Relation
-
#targeted_left_join(target: 'subject', target_class: ::Otu) ⇒ ActiveRecord::Relation
Not used.
Methods included from Shared::QueryBatchUpdate
Methods included from DwcExtensions
#darwin_core_extension_json, #darwin_core_extension_row, #dwc_related_resource, #dwc_related_resource_id, #dwc_relationship_according_to, #dwc_relationship_established_date, #dwc_relationship_of_resource, #dwc_relationship_of_resource_id, #dwc_relationship_remarks, #dwc_resource, #dwc_resource_id, #dwc_resource_relationship_coreid, #dwc_resource_relationship_id, #globi_extension_json
Methods included from GlobiExtensions
#globi_extension_json, #globi_extension_row, #globi_interaction_type_id, #globi_interaction_type_name, #globi_source_catalog_number, #globi_source_collection_code, #globi_source_institution_code, #globi_source_life_stage_id, #globi_source_life_stage_name, #globi_source_occurrence_id, #globi_source_sex_id, #globi_source_sex_name, #globi_source_taxon_name, #globi_source_taxon_path, #globi_source_taxon_rank, #globi_target_catalog_number, #globi_target_collection_code, #globi_target_institution_code, #globi_target_life_stage_id, #globi_target_life_stage_name, #globi_target_occurrence_id, #globi_target_sex_id, #globi_target_sex_name, #globi_target_taxon_name, #globi_target_taxon_path, #globi_target_taxon_rank
Methods included from Shared::IsData
#errors_excepting, #full_error_messages_excepting, #identical, #is_community?, #is_destroyable?, #is_editable?, #is_in_use?, #is_in_users_projects?, #metamorphosize, #similar
Methods included from Shared::AutoUuid
#create_object_uuid, #generate_uuid_if_required
Methods included from Shared::Depictions
#has_depictions?, #image_array=, #reject_depictions, #reject_images
Methods included from Shared::Confidences
Methods included from Shared::Notes
#concatenated_notes_string, #reject_notes
Methods included from Shared::DataAttributes
#import_attributes, #internal_attributes, #keyword_value_hash, #reject_data_attributes
Methods included from Shared::Identifiers
#dwc_occurrence_id, #identified?, #next_by_identifier, #previous_by_identifier, #reject_identifiers, #uri, #uuid
Methods included from Shared::Tags
#reject_tags, #tag_with, #tagged?, #tagged_with?
Methods included from Shared::Citations
#cited?, #mark_citations_for_destruction, #nomenclature_date, #origin_citation_source_id, #reject_citations, #requires_citation?, #sources_by_topic_id
Methods included from SoftValidation
#clear_soft_validations, #fix_for, #fix_soft_validations, #soft_fixed?, #soft_valid?, #soft_validate, #soft_validated?, #soft_validations, #soft_validators
Methods included from Housekeeping
#has_polymorphic_relationship?
Methods inherited from ApplicationRecord
Instance Attribute Details
#biological_association_object_id ⇒ Integer
Returns Rails polymorphic, id of the object.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/models/biological_association.rb', line 29 class BiologicalAssociation < ApplicationRecord include Housekeeping include SoftValidation include Shared::Citations include Shared::Tags include Shared::Identifiers include Shared::DataAttributes include Shared::Notes include Shared::Confidences include Shared::Depictions include Shared::AutoUuid include Shared::AssertedDistributions include Shared::IsData include BiologicalAssociation::GlobiExtensions include BiologicalAssociation::DwcExtensions include Shared::QueryBatchUpdate GRAPH_ENTRY_POINTS = [:asserted_distributions].freeze belongs_to :biological_relationship, inverse_of: :biological_associations has_many :subject_biological_relationship_types, through: :biological_relationship has_many :object_biological_relationship_types, through: :biological_relationship has_many :subject_biological_properties, through: :subject_biological_relationship_types, source: :biological_property has_many :object_biological_properties, through: :object_biological_relationship_types, source: :biological_property belongs_to :biological_association_subject, polymorphic: true, inverse_of: :biological_associations belongs_to :biological_association_object, polymorphic: true, inverse_of: :related_biological_associations has_many :biological_associations_biological_associations_graphs, inverse_of: :biological_association, dependent: :destroy has_many :biological_associations_graphs, through: :biological_associations_biological_associations_graphs, inverse_of: :biological_associations validates_presence_of :biological_relationship validates_presence_of :biological_association_subject validates_presence_of :biological_association_object validate :association_is_unique validate :biological_association_subject_type_is_allowed validate :biological_association_object_type_is_allowed attr_accessor :subject_global_id attr_accessor :object_global_id # TODO: this is badly named attr_accessor :rotate def rotate=(value) s = self.biological_association_subject o = self.biological_association_object self.biological_association_subject = o self.biological_association_object = s end def subject_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_subject_id, o.id) write_attribute(:biological_association_subject_type, o..class.name) end def object_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_object_id, o.id) write_attribute(:biological_association_object_type, o..class.name) end # TODO: Why?! this is just biological_association.biological_association_subject_type def subject_class_name biological_association_subject.try(:class).base_class.name end # TODO: Why?! this is just biological_association.biological_association_object_type def object_class_name biological_association_object.try(:class).base_class.name end # !! You can not set with this method def subject biological_association_subject end # !! You can not set with this method def object biological_association_object end class << self def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end end def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end # @return [ActiveRecord::Relation] def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [ActiveRecord::Relation] def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end # Not used # @return [ActiveRecord::Relation] def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [Scope] # the max 10 most recently used def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end private def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end end |
#biological_association_object_type ⇒ String
Returns Rails polymorphic, type of the object (e.g. CollectionObject).
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/models/biological_association.rb', line 29 class BiologicalAssociation < ApplicationRecord include Housekeeping include SoftValidation include Shared::Citations include Shared::Tags include Shared::Identifiers include Shared::DataAttributes include Shared::Notes include Shared::Confidences include Shared::Depictions include Shared::AutoUuid include Shared::AssertedDistributions include Shared::IsData include BiologicalAssociation::GlobiExtensions include BiologicalAssociation::DwcExtensions include Shared::QueryBatchUpdate GRAPH_ENTRY_POINTS = [:asserted_distributions].freeze belongs_to :biological_relationship, inverse_of: :biological_associations has_many :subject_biological_relationship_types, through: :biological_relationship has_many :object_biological_relationship_types, through: :biological_relationship has_many :subject_biological_properties, through: :subject_biological_relationship_types, source: :biological_property has_many :object_biological_properties, through: :object_biological_relationship_types, source: :biological_property belongs_to :biological_association_subject, polymorphic: true, inverse_of: :biological_associations belongs_to :biological_association_object, polymorphic: true, inverse_of: :related_biological_associations has_many :biological_associations_biological_associations_graphs, inverse_of: :biological_association, dependent: :destroy has_many :biological_associations_graphs, through: :biological_associations_biological_associations_graphs, inverse_of: :biological_associations validates_presence_of :biological_relationship validates_presence_of :biological_association_subject validates_presence_of :biological_association_object validate :association_is_unique validate :biological_association_subject_type_is_allowed validate :biological_association_object_type_is_allowed attr_accessor :subject_global_id attr_accessor :object_global_id # TODO: this is badly named attr_accessor :rotate def rotate=(value) s = self.biological_association_subject o = self.biological_association_object self.biological_association_subject = o self.biological_association_object = s end def subject_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_subject_id, o.id) write_attribute(:biological_association_subject_type, o..class.name) end def object_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_object_id, o.id) write_attribute(:biological_association_object_type, o..class.name) end # TODO: Why?! this is just biological_association.biological_association_subject_type def subject_class_name biological_association_subject.try(:class).base_class.name end # TODO: Why?! this is just biological_association.biological_association_object_type def object_class_name biological_association_object.try(:class).base_class.name end # !! You can not set with this method def subject biological_association_subject end # !! You can not set with this method def object biological_association_object end class << self def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end end def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end # @return [ActiveRecord::Relation] def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [ActiveRecord::Relation] def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end # Not used # @return [ActiveRecord::Relation] def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [Scope] # the max 10 most recently used def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end private def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end end |
#biological_association_subject_id ⇒ Integer
Returns Rails polymorphic, id of the subject of the relationship.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/models/biological_association.rb', line 29 class BiologicalAssociation < ApplicationRecord include Housekeeping include SoftValidation include Shared::Citations include Shared::Tags include Shared::Identifiers include Shared::DataAttributes include Shared::Notes include Shared::Confidences include Shared::Depictions include Shared::AutoUuid include Shared::AssertedDistributions include Shared::IsData include BiologicalAssociation::GlobiExtensions include BiologicalAssociation::DwcExtensions include Shared::QueryBatchUpdate GRAPH_ENTRY_POINTS = [:asserted_distributions].freeze belongs_to :biological_relationship, inverse_of: :biological_associations has_many :subject_biological_relationship_types, through: :biological_relationship has_many :object_biological_relationship_types, through: :biological_relationship has_many :subject_biological_properties, through: :subject_biological_relationship_types, source: :biological_property has_many :object_biological_properties, through: :object_biological_relationship_types, source: :biological_property belongs_to :biological_association_subject, polymorphic: true, inverse_of: :biological_associations belongs_to :biological_association_object, polymorphic: true, inverse_of: :related_biological_associations has_many :biological_associations_biological_associations_graphs, inverse_of: :biological_association, dependent: :destroy has_many :biological_associations_graphs, through: :biological_associations_biological_associations_graphs, inverse_of: :biological_associations validates_presence_of :biological_relationship validates_presence_of :biological_association_subject validates_presence_of :biological_association_object validate :association_is_unique validate :biological_association_subject_type_is_allowed validate :biological_association_object_type_is_allowed attr_accessor :subject_global_id attr_accessor :object_global_id # TODO: this is badly named attr_accessor :rotate def rotate=(value) s = self.biological_association_subject o = self.biological_association_object self.biological_association_subject = o self.biological_association_object = s end def subject_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_subject_id, o.id) write_attribute(:biological_association_subject_type, o..class.name) end def object_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_object_id, o.id) write_attribute(:biological_association_object_type, o..class.name) end # TODO: Why?! this is just biological_association.biological_association_subject_type def subject_class_name biological_association_subject.try(:class).base_class.name end # TODO: Why?! this is just biological_association.biological_association_object_type def object_class_name biological_association_object.try(:class).base_class.name end # !! You can not set with this method def subject biological_association_subject end # !! You can not set with this method def object biological_association_object end class << self def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end end def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end # @return [ActiveRecord::Relation] def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [ActiveRecord::Relation] def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end # Not used # @return [ActiveRecord::Relation] def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [Scope] # the max 10 most recently used def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end private def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end end |
#biological_association_subject_type ⇒ String
Returns Rails polymorphic, type fo the subject (e.g. Otu).
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/models/biological_association.rb', line 29 class BiologicalAssociation < ApplicationRecord include Housekeeping include SoftValidation include Shared::Citations include Shared::Tags include Shared::Identifiers include Shared::DataAttributes include Shared::Notes include Shared::Confidences include Shared::Depictions include Shared::AutoUuid include Shared::AssertedDistributions include Shared::IsData include BiologicalAssociation::GlobiExtensions include BiologicalAssociation::DwcExtensions include Shared::QueryBatchUpdate GRAPH_ENTRY_POINTS = [:asserted_distributions].freeze belongs_to :biological_relationship, inverse_of: :biological_associations has_many :subject_biological_relationship_types, through: :biological_relationship has_many :object_biological_relationship_types, through: :biological_relationship has_many :subject_biological_properties, through: :subject_biological_relationship_types, source: :biological_property has_many :object_biological_properties, through: :object_biological_relationship_types, source: :biological_property belongs_to :biological_association_subject, polymorphic: true, inverse_of: :biological_associations belongs_to :biological_association_object, polymorphic: true, inverse_of: :related_biological_associations has_many :biological_associations_biological_associations_graphs, inverse_of: :biological_association, dependent: :destroy has_many :biological_associations_graphs, through: :biological_associations_biological_associations_graphs, inverse_of: :biological_associations validates_presence_of :biological_relationship validates_presence_of :biological_association_subject validates_presence_of :biological_association_object validate :association_is_unique validate :biological_association_subject_type_is_allowed validate :biological_association_object_type_is_allowed attr_accessor :subject_global_id attr_accessor :object_global_id # TODO: this is badly named attr_accessor :rotate def rotate=(value) s = self.biological_association_subject o = self.biological_association_object self.biological_association_subject = o self.biological_association_object = s end def subject_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_subject_id, o.id) write_attribute(:biological_association_subject_type, o..class.name) end def object_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_object_id, o.id) write_attribute(:biological_association_object_type, o..class.name) end # TODO: Why?! this is just biological_association.biological_association_subject_type def subject_class_name biological_association_subject.try(:class).base_class.name end # TODO: Why?! this is just biological_association.biological_association_object_type def object_class_name biological_association_object.try(:class).base_class.name end # !! You can not set with this method def subject biological_association_subject end # !! You can not set with this method def object biological_association_object end class << self def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end end def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end # @return [ActiveRecord::Relation] def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [ActiveRecord::Relation] def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end # Not used # @return [ActiveRecord::Relation] def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [Scope] # the max 10 most recently used def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end private def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end end |
#biological_relationship_id ⇒ Integer
Returns the BiologicalRelationship id.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/models/biological_association.rb', line 29 class BiologicalAssociation < ApplicationRecord include Housekeeping include SoftValidation include Shared::Citations include Shared::Tags include Shared::Identifiers include Shared::DataAttributes include Shared::Notes include Shared::Confidences include Shared::Depictions include Shared::AutoUuid include Shared::AssertedDistributions include Shared::IsData include BiologicalAssociation::GlobiExtensions include BiologicalAssociation::DwcExtensions include Shared::QueryBatchUpdate GRAPH_ENTRY_POINTS = [:asserted_distributions].freeze belongs_to :biological_relationship, inverse_of: :biological_associations has_many :subject_biological_relationship_types, through: :biological_relationship has_many :object_biological_relationship_types, through: :biological_relationship has_many :subject_biological_properties, through: :subject_biological_relationship_types, source: :biological_property has_many :object_biological_properties, through: :object_biological_relationship_types, source: :biological_property belongs_to :biological_association_subject, polymorphic: true, inverse_of: :biological_associations belongs_to :biological_association_object, polymorphic: true, inverse_of: :related_biological_associations has_many :biological_associations_biological_associations_graphs, inverse_of: :biological_association, dependent: :destroy has_many :biological_associations_graphs, through: :biological_associations_biological_associations_graphs, inverse_of: :biological_associations validates_presence_of :biological_relationship validates_presence_of :biological_association_subject validates_presence_of :biological_association_object validate :association_is_unique validate :biological_association_subject_type_is_allowed validate :biological_association_object_type_is_allowed attr_accessor :subject_global_id attr_accessor :object_global_id # TODO: this is badly named attr_accessor :rotate def rotate=(value) s = self.biological_association_subject o = self.biological_association_object self.biological_association_subject = o self.biological_association_object = s end def subject_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_subject_id, o.id) write_attribute(:biological_association_subject_type, o..class.name) end def object_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_object_id, o.id) write_attribute(:biological_association_object_type, o..class.name) end # TODO: Why?! this is just biological_association.biological_association_subject_type def subject_class_name biological_association_subject.try(:class).base_class.name end # TODO: Why?! this is just biological_association.biological_association_object_type def object_class_name biological_association_object.try(:class).base_class.name end # !! You can not set with this method def subject biological_association_subject end # !! You can not set with this method def object biological_association_object end class << self def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end end def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end # @return [ActiveRecord::Relation] def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [ActiveRecord::Relation] def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end # Not used # @return [ActiveRecord::Relation] def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [Scope] # the max 10 most recently used def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end private def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end end |
#object_global_id ⇒ Object
TODO: this is badly named
74 75 76 |
# File 'app/models/biological_association.rb', line 74 def object_global_id @object_global_id end |
#project_id ⇒ Integer
the project ID
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/models/biological_association.rb', line 29 class BiologicalAssociation < ApplicationRecord include Housekeeping include SoftValidation include Shared::Citations include Shared::Tags include Shared::Identifiers include Shared::DataAttributes include Shared::Notes include Shared::Confidences include Shared::Depictions include Shared::AutoUuid include Shared::AssertedDistributions include Shared::IsData include BiologicalAssociation::GlobiExtensions include BiologicalAssociation::DwcExtensions include Shared::QueryBatchUpdate GRAPH_ENTRY_POINTS = [:asserted_distributions].freeze belongs_to :biological_relationship, inverse_of: :biological_associations has_many :subject_biological_relationship_types, through: :biological_relationship has_many :object_biological_relationship_types, through: :biological_relationship has_many :subject_biological_properties, through: :subject_biological_relationship_types, source: :biological_property has_many :object_biological_properties, through: :object_biological_relationship_types, source: :biological_property belongs_to :biological_association_subject, polymorphic: true, inverse_of: :biological_associations belongs_to :biological_association_object, polymorphic: true, inverse_of: :related_biological_associations has_many :biological_associations_biological_associations_graphs, inverse_of: :biological_association, dependent: :destroy has_many :biological_associations_graphs, through: :biological_associations_biological_associations_graphs, inverse_of: :biological_associations validates_presence_of :biological_relationship validates_presence_of :biological_association_subject validates_presence_of :biological_association_object validate :association_is_unique validate :biological_association_subject_type_is_allowed validate :biological_association_object_type_is_allowed attr_accessor :subject_global_id attr_accessor :object_global_id # TODO: this is badly named attr_accessor :rotate def rotate=(value) s = self.biological_association_subject o = self.biological_association_object self.biological_association_subject = o self.biological_association_object = s end def subject_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_subject_id, o.id) write_attribute(:biological_association_subject_type, o..class.name) end def object_global_id=(value) o = GlobalID::Locator.locate(value) write_attribute(:biological_association_object_id, o.id) write_attribute(:biological_association_object_type, o..class.name) end # TODO: Why?! this is just biological_association.biological_association_subject_type def subject_class_name biological_association_subject.try(:class).base_class.name end # TODO: Why?! this is just biological_association.biological_association_object_type def object_class_name biological_association_object.try(:class).base_class.name end # !! You can not set with this method def subject biological_association_subject end # !! You can not set with this method def object biological_association_object end class << self def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end end def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end # @return [ActiveRecord::Relation] def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [ActiveRecord::Relation] def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end # Not used # @return [ActiveRecord::Relation] def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end # @return [Scope] # the max 10 most recently used def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end private def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end end |
#rotate ⇒ Object
Returns the value of attribute rotate.
76 77 78 |
# File 'app/models/biological_association.rb', line 76 def rotate @rotate end |
#subject_global_id ⇒ Object
Returns the value of attribute subject_global_id.
73 74 75 |
# File 'app/models/biological_association.rb', line 73 def subject_global_id @subject_global_id end |
Class Method Details
.batch_update(params) ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'app/models/biological_association.rb', line 142 def batch_update(params) request = QueryBatchRequest.new( klass: 'BiologicalAssociation', object_filter_params: params[:biological_association_query], object_params: params[:biological_association], async_cutoff: (params[:async_cutoff] || 26), preview: params[:preview] ) set_batch_cap(request) query_batch_update(request) end |
.select_optimized(user_id, project_id, klass) ⇒ Object
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'app/models/biological_association.rb', line 226 def self.select_optimized(user_id, project_id, klass) r = used_recently(user_id, project_id, klass) h = { quick: [], pinboard: BiologicalAssociation.pinned_by(user_id).where(project_id: project_id).to_a, recent: [] } if r.empty? h[:quick] = BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a else h[:recent] = BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(10) ).order(updated_at: :desc).to_a h[:quick] = (BiologicalAssociation.pinned_by(user_id).pinboard_inserted.where(project_id: project_id).to_a + BiologicalAssociation.where('"biological_associations"."id" IN (?)', r.first(4) ).order(updated_at: :desc).to_a).uniq end h end |
.set_batch_cap(request) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'app/models/biological_association.rb', line 120 def set_batch_cap(request) a = request.filter total = a.all.pluck(:biological_relationship_id).uniq cap = 0 case total.size when 1 cap = 5000 request.cap_reason = 'Maximum allowed.' when 2 cap = 2000 request.cap_reason = 'Maximum allowed when 2 biological relationships present.' else cap = 25 request.cap_reason = 'Maximum allowed when 3 or more biological relationships present.' end request.cap = cap request end |
.used_recently(user_id, project_id, used_on) ⇒ Scope
Returns the max 10 most recently used.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'app/models/biological_association.rb', line 193 def self.used_recently(user_id, project_id, used_on) t = case used_on when 'AssertedDistribution' AssertedDistribution.arel_table else return BiologicalAssociation.none end # i is a select manager i = case used_on when 'AssertedDistribution' t.project(t['asserted_distribution_object_id'], t['updated_at']).from(t) .where( t['updated_at'].gt(1.week.ago).and( t['asserted_distribution_object_type'].eq('BiologicalAssociation') ) ) .where(t['updated_by_id'].eq(user_id)) .where(t['project_id'].eq(project_id)) .order(t['updated_at'].desc) end z = i.as('recent_t') p = BiologicalAssociation.arel_table case used_on when 'AssertedDistribution' BiologicalAssociation.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['asserted_distribution_object_id'].eq(p['id']))) ).pluck(:id).uniq end end |
Instance Method Details
#association_is_unique ⇒ Object (private)
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'app/models/biological_association.rb', line 247 def association_is_unique if a = BiologicalAssociation.where.not(id:).where( biological_association_subject:, biological_association_object:, biological_relationship: ).first # For unify purposes, self has changed either subject or object, a is the # identical BA we will perhaps unify with. if will_save_change_to_biological_association_subject_id? errors.add(:biological_association_subject, 'has already been taken') elsif will_save_change_to_biological_association_object_id? errors.add(:biological_association_object, 'has already been taken') else errors.add(:biological_association, 'already exists') end end end |
#biological_association_object_type_is_allowed ⇒ Object (private)
270 271 272 |
# File 'app/models/biological_association.rb', line 270 def biological_association_object_type_is_allowed errors.add(:biological_association_object_type, 'is not permitted') unless biological_association_object && biological_association_object.class.is_biologically_relatable? end |
#biological_association_subject_type_is_allowed ⇒ Object (private)
266 267 268 |
# File 'app/models/biological_association.rb', line 266 def biological_association_subject_type_is_allowed errors.add(:biological_association_subject_type, 'is not permitted') unless biological_association_subject && biological_association_subject.class.is_biologically_relatable? end |
#dwc_extension_select ⇒ Object
157 158 159 160 161 162 |
# File 'app/models/biological_association.rb', line 157 def dwc_extension_select BiologicalAssociation .joins("LEFT JOIN identifiers id_s ON id_s.identifier_object_type = biological_associations.biological_associations_subject_type AND ids_s.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_o ON id_o.identifier_object_type = biological_associations.biological_associations_object_type AND ids_o.type = 'Identifier::Global::Uuid'" ) .joins("LEFT JOIN identifiers id_r ON id_o.identifier_object_type = 'BiologicalRelationship' AND idr_.identifier_object_id = biological_associations.biological_relationship_id AND ids_r.type = 'Identifier::Global::Uri'" ) end |
#object ⇒ Object
!! You can not set with this method
114 115 116 |
# File 'app/models/biological_association.rb', line 114 def object biological_association_object end |
#object_class_name ⇒ Object
TODO: Why?! this is just biological_association.biological_association_object_type
104 105 106 |
# File 'app/models/biological_association.rb', line 104 def object_class_name biological_association_object.try(:class).base_class.name end |
#subject ⇒ Object
!! You can not set with this method
109 110 111 |
# File 'app/models/biological_association.rb', line 109 def subject biological_association_subject end |
#subject_class_name ⇒ Object
TODO: Why?! this is just biological_association.biological_association_subject_type
99 100 101 |
# File 'app/models/biological_association.rb', line 99 def subject_class_name biological_association_subject.try(:class).base_class.name end |
#targeted_join(target: 'subject', target_class: ::Otu) ⇒ ActiveRecord::Relation
165 166 167 168 169 170 171 |
# File 'app/models/biological_association.rb', line 165 def targeted_join(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end |
#targeted_join2(target: 'subject', target_class: ::Otu) ⇒ ActiveRecord::Relation
174 175 176 177 178 179 |
# File 'app/models/biological_association.rb', line 174 def targeted_join2(target: 'subject', target_class: ::Otu) a = arel_table b = target_class.arel_table j = a.join(b).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) end |
#targeted_left_join(target: 'subject', target_class: ::Otu) ⇒ ActiveRecord::Relation
Not used
183 184 185 186 187 188 189 |
# File 'app/models/biological_association.rb', line 183 def targeted_left_join(target: 'subject', target_class: ::Otu ) a = arel_table b = target_class.arel_table j = a.join(b, Arel::Nodes::OuterJoin).on(a["biological_association_#{target}_type".to_sym].eq(target_class.name).and(a["biological_assoication_#{target}_id".to_sym].eq(b[:id]))) joins(j.join_sources) end |