Class: ObservationMatrixRowItem

Inherits:
ApplicationRecord show all
Includes:
Housekeeping, Shared::Citations, Shared::Identifiers, Shared::IsData, Shared::Notes, Shared::Tags
Defined in:
app/models/observation_matrix_row_item.rb

Overview

Each ObservationMatrixRowItem is set of Otus or Collection Objects (1 or more)

Direct Known Subclasses

SingleCollectionObject, SingleOtu, TaggedRowItem

Defined Under Namespace

Classes: SingleCollectionObject, SingleOtu, TaggedRowItem

Constant Summary

ALL_STI_ATTRIBUTES =
[:otu_id, :collection_object_id, :controlled_vocabulary_term_id].freeze

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Housekeeping

#has_polymorphic_relationship?

Methods included from ActiverecordUtilities

#trim_attributes

Instance Attribute Details

- (Integer) cached_observation_matrix_row_item_id

Returns if the column item is derived from a ::Single<FOO> subclass, the id of that instance

Returns:

  • (Integer)

    if the column item is derived from a ::Single<FOO> subclass, the id of that instance



18
19
20
21
22
23
24
25
26
27
28
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
# File 'app/models/observation_matrix_row_item.rb', line 18

class ObservationMatrixRowItem < ApplicationRecord
  include Housekeeping
  include Shared::Citations
  include Shared::Identifiers
  include Shared::IsData
  include Shared::Tags
  include Shared::Notes

  acts_as_list scope: [:observation_matrix_id, :project_id]

  ALL_STI_ATTRIBUTES = [:otu_id, :collection_object_id, :controlled_vocabulary_term_id].freeze

  belongs_to :observation_matrix, inverse_of: :observation_matrix_row_items
  belongs_to :otu, inverse_of: :observation_matrix_row_items
  belongs_to :collection_object, inverse_of: :observation_matrix_row_items

  validates_presence_of :observation_matrix
  validate :type_is_subclassed
  validate :other_subclass_attributes_not_set, if: -> {!type.blank?}

  after_save :update_matrix_rows
  after_destroy :cleanup_matrix_rows

  def update_matrix_rows
    objects = Array.new
    objects.push *otus if otus
    objects.push *collection_objects if collection_objects

    objects.each do |o|
      update_single_matrix_row o
    end
  end

  def cleanup_matrix_rows
    rows = []
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: otus.map(&:id)) if otus
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: collection_objects.map(&:id)) if collection_objects

    rows.each do |mr|
      decrement_matrix_row_reference_count(mr)
    end
  end

  def update_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, otu: object )
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, collection_object: object)
    end
    increment_matrix_row_reference_count(mr)
  end

  def cleanup_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: object.id).first
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: object.id).first
    end

    decrement_matrix_row_reference_count(mr)
  end

  def self.human_name
    self.name.demodulize.humanize
  end

  # @return [Array]
  #   the otus "defined" by this matrix row item
  # override
  def otus
    false
  end

  # @return [Array]
  #   the collection objects "defined" by this matrix row item
  # override
  def collection_objects
    false
  end

  # @return [Array]
  #   the required attributes for this subclass
  # override
  def self.subclass_attributes
    []
  end

  # @return [Object]
  #   the object used to define the set of matrix rows
  # override
  def matrix_row_item_object
    nil
  end

  # @return [matrix_row_item_object, nil]
  def object_is?(object_type)
    matrix_row_item_object.class.name == object_type ? matrix_row_item_object : nil
  end

  # @return [Boolean]
  #   whether this is a dynamic or fixed class
  #   override in subclasses
  def is_dynamic?
    false
  end

  protected

  def other_subclass_attributes_not_set
    (ALL_STI_ATTRIBUTES - self.type.constantize.subclass_attributes).each do |attr|
      errors.add(attr, 'is not valid for this type of observation matrix row item') if !send(attr).blank?
    end
  end

  def type_is_subclassed
    if !MATRIX_ROW_ITEM_TYPES[type]
      errors.add(:type, 'type must be a valid subclass')
    end
  end

  # @return [Array] of ObservationMatrixRowItems
  def self.batch_create(params)
    case params[:batch_type]
    when 'tags'
      batch_create_from_tags(params[:keyword_id], params[:klass], params[:observation_matrix_id])
    when 'pinboard'
      batch_create_from_pinboard(params[:observation_matrix_id], params[:project_id], params[:user_id], params[:klass])
    end
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_tags(keyword_id, klass, observation_matrix_id)
    created = []
    ObservationMatrixRowItem.transaction do
      begin
        if klass
          klass.constantize.joins(:tags).where(tags: {keyword_id: keyword_id} ).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_tags(
            Tag.where(keyword_id: keyword_id, tag_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )       
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass)
    return false if observation_matrix_id.blank? || project_id.blank? || user_id.blank?
    created = []
    ObservationMatrixRow.transaction do
      begin
        if klass
          klass.constantize.joins(:pinboard_items).where(pinboard_items: {user_id: user_id, project_id: project_id}).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_pinboard_items(
            PinboardItem.where(project_id: project_id, user_id: user_id, pinned_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  private

  # @return [Array]
  def self.create_for_tags(tag_scope, observation_matrix_id)
    a = []
    tag_scope.each do |o|
      a.push create_for(o.tag_object, observation_matrix_id)
    end
    a
  end

  # @param pinboard_item_scope [PinboardItem Scope]
  # @return [Array]
  #   create observation matrix row items for all scope items
  def self.create_for_pinboard_items(pinboard_item_scope, observation_matrix_id)
    a = []
    pinboard_item_scope.each do |o|
      a.push create_for(o.pinned_object, observation_matrix_id)
    end
    a 
  end

  def self.create_for(object, observation_matrix_id)
    p = { observation_matrix_id: observation_matrix_id }
    case object.class.base_class.name
    when 'Otu'
      p[:otu_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleOtu'
    when 'CollectionObject'
      p[:collection_object_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleCollectionObject'
    else
      raise 
    end
    ObservationMatrixRowItem.create!(p)
  end

  def decrement_matrix_row_reference_count(mr)
    current = mr.reference_count - 1

    if current == 0
      mr.delete
    else
      mr.update_columns(reference_count: current)
      mr.update_columns(cached_observation_matrix_row_item_id: nil) if current == 1 && type =~ /Single/ # we've deleted the only single, so the last must be a Dynamic/Tagged
    end
  end

  def increment_matrix_row_reference_count(mr)
    mr.update_columns(reference_count: mr.reference_count + 1)
    mr.update_columns(cached_observation_matrix_row_item_id: id) if type =~ /Single/
  end

end

- (Integer) collection_object_id

Returns id of a (single) CollectObject based row

Returns:

  • (Integer)

    id of a (single) CollectObject based row



18
19
20
21
22
23
24
25
26
27
28
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
# File 'app/models/observation_matrix_row_item.rb', line 18

class ObservationMatrixRowItem < ApplicationRecord
  include Housekeeping
  include Shared::Citations
  include Shared::Identifiers
  include Shared::IsData
  include Shared::Tags
  include Shared::Notes

  acts_as_list scope: [:observation_matrix_id, :project_id]

  ALL_STI_ATTRIBUTES = [:otu_id, :collection_object_id, :controlled_vocabulary_term_id].freeze

  belongs_to :observation_matrix, inverse_of: :observation_matrix_row_items
  belongs_to :otu, inverse_of: :observation_matrix_row_items
  belongs_to :collection_object, inverse_of: :observation_matrix_row_items

  validates_presence_of :observation_matrix
  validate :type_is_subclassed
  validate :other_subclass_attributes_not_set, if: -> {!type.blank?}

  after_save :update_matrix_rows
  after_destroy :cleanup_matrix_rows

  def update_matrix_rows
    objects = Array.new
    objects.push *otus if otus
    objects.push *collection_objects if collection_objects

    objects.each do |o|
      update_single_matrix_row o
    end
  end

  def cleanup_matrix_rows
    rows = []
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: otus.map(&:id)) if otus
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: collection_objects.map(&:id)) if collection_objects

    rows.each do |mr|
      decrement_matrix_row_reference_count(mr)
    end
  end

  def update_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, otu: object )
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, collection_object: object)
    end
    increment_matrix_row_reference_count(mr)
  end

  def cleanup_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: object.id).first
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: object.id).first
    end

    decrement_matrix_row_reference_count(mr)
  end

  def self.human_name
    self.name.demodulize.humanize
  end

  # @return [Array]
  #   the otus "defined" by this matrix row item
  # override
  def otus
    false
  end

  # @return [Array]
  #   the collection objects "defined" by this matrix row item
  # override
  def collection_objects
    false
  end

  # @return [Array]
  #   the required attributes for this subclass
  # override
  def self.subclass_attributes
    []
  end

  # @return [Object]
  #   the object used to define the set of matrix rows
  # override
  def matrix_row_item_object
    nil
  end

  # @return [matrix_row_item_object, nil]
  def object_is?(object_type)
    matrix_row_item_object.class.name == object_type ? matrix_row_item_object : nil
  end

  # @return [Boolean]
  #   whether this is a dynamic or fixed class
  #   override in subclasses
  def is_dynamic?
    false
  end

  protected

  def other_subclass_attributes_not_set
    (ALL_STI_ATTRIBUTES - self.type.constantize.subclass_attributes).each do |attr|
      errors.add(attr, 'is not valid for this type of observation matrix row item') if !send(attr).blank?
    end
  end

  def type_is_subclassed
    if !MATRIX_ROW_ITEM_TYPES[type]
      errors.add(:type, 'type must be a valid subclass')
    end
  end

  # @return [Array] of ObservationMatrixRowItems
  def self.batch_create(params)
    case params[:batch_type]
    when 'tags'
      batch_create_from_tags(params[:keyword_id], params[:klass], params[:observation_matrix_id])
    when 'pinboard'
      batch_create_from_pinboard(params[:observation_matrix_id], params[:project_id], params[:user_id], params[:klass])
    end
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_tags(keyword_id, klass, observation_matrix_id)
    created = []
    ObservationMatrixRowItem.transaction do
      begin
        if klass
          klass.constantize.joins(:tags).where(tags: {keyword_id: keyword_id} ).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_tags(
            Tag.where(keyword_id: keyword_id, tag_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )       
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass)
    return false if observation_matrix_id.blank? || project_id.blank? || user_id.blank?
    created = []
    ObservationMatrixRow.transaction do
      begin
        if klass
          klass.constantize.joins(:pinboard_items).where(pinboard_items: {user_id: user_id, project_id: project_id}).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_pinboard_items(
            PinboardItem.where(project_id: project_id, user_id: user_id, pinned_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  private

  # @return [Array]
  def self.create_for_tags(tag_scope, observation_matrix_id)
    a = []
    tag_scope.each do |o|
      a.push create_for(o.tag_object, observation_matrix_id)
    end
    a
  end

  # @param pinboard_item_scope [PinboardItem Scope]
  # @return [Array]
  #   create observation matrix row items for all scope items
  def self.create_for_pinboard_items(pinboard_item_scope, observation_matrix_id)
    a = []
    pinboard_item_scope.each do |o|
      a.push create_for(o.pinned_object, observation_matrix_id)
    end
    a 
  end

  def self.create_for(object, observation_matrix_id)
    p = { observation_matrix_id: observation_matrix_id }
    case object.class.base_class.name
    when 'Otu'
      p[:otu_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleOtu'
    when 'CollectionObject'
      p[:collection_object_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleCollectionObject'
    else
      raise 
    end
    ObservationMatrixRowItem.create!(p)
  end

  def decrement_matrix_row_reference_count(mr)
    current = mr.reference_count - 1

    if current == 0
      mr.delete
    else
      mr.update_columns(reference_count: current)
      mr.update_columns(cached_observation_matrix_row_item_id: nil) if current == 1 && type =~ /Single/ # we've deleted the only single, so the last must be a Dynamic/Tagged
    end
  end

  def increment_matrix_row_reference_count(mr)
    mr.update_columns(reference_count: mr.reference_count + 1)
    mr.update_columns(cached_observation_matrix_row_item_id: id) if type =~ /Single/
  end

end

- (Integer) observation_matrix_id

Returns id of the matrix

Returns:

  • (Integer)

    id of the matrix



18
19
20
21
22
23
24
25
26
27
28
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
# File 'app/models/observation_matrix_row_item.rb', line 18

class ObservationMatrixRowItem < ApplicationRecord
  include Housekeeping
  include Shared::Citations
  include Shared::Identifiers
  include Shared::IsData
  include Shared::Tags
  include Shared::Notes

  acts_as_list scope: [:observation_matrix_id, :project_id]

  ALL_STI_ATTRIBUTES = [:otu_id, :collection_object_id, :controlled_vocabulary_term_id].freeze

  belongs_to :observation_matrix, inverse_of: :observation_matrix_row_items
  belongs_to :otu, inverse_of: :observation_matrix_row_items
  belongs_to :collection_object, inverse_of: :observation_matrix_row_items

  validates_presence_of :observation_matrix
  validate :type_is_subclassed
  validate :other_subclass_attributes_not_set, if: -> {!type.blank?}

  after_save :update_matrix_rows
  after_destroy :cleanup_matrix_rows

  def update_matrix_rows
    objects = Array.new
    objects.push *otus if otus
    objects.push *collection_objects if collection_objects

    objects.each do |o|
      update_single_matrix_row o
    end
  end

  def cleanup_matrix_rows
    rows = []
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: otus.map(&:id)) if otus
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: collection_objects.map(&:id)) if collection_objects

    rows.each do |mr|
      decrement_matrix_row_reference_count(mr)
    end
  end

  def update_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, otu: object )
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, collection_object: object)
    end
    increment_matrix_row_reference_count(mr)
  end

  def cleanup_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: object.id).first
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: object.id).first
    end

    decrement_matrix_row_reference_count(mr)
  end

  def self.human_name
    self.name.demodulize.humanize
  end

  # @return [Array]
  #   the otus "defined" by this matrix row item
  # override
  def otus
    false
  end

  # @return [Array]
  #   the collection objects "defined" by this matrix row item
  # override
  def collection_objects
    false
  end

  # @return [Array]
  #   the required attributes for this subclass
  # override
  def self.subclass_attributes
    []
  end

  # @return [Object]
  #   the object used to define the set of matrix rows
  # override
  def matrix_row_item_object
    nil
  end

  # @return [matrix_row_item_object, nil]
  def object_is?(object_type)
    matrix_row_item_object.class.name == object_type ? matrix_row_item_object : nil
  end

  # @return [Boolean]
  #   whether this is a dynamic or fixed class
  #   override in subclasses
  def is_dynamic?
    false
  end

  protected

  def other_subclass_attributes_not_set
    (ALL_STI_ATTRIBUTES - self.type.constantize.subclass_attributes).each do |attr|
      errors.add(attr, 'is not valid for this type of observation matrix row item') if !send(attr).blank?
    end
  end

  def type_is_subclassed
    if !MATRIX_ROW_ITEM_TYPES[type]
      errors.add(:type, 'type must be a valid subclass')
    end
  end

  # @return [Array] of ObservationMatrixRowItems
  def self.batch_create(params)
    case params[:batch_type]
    when 'tags'
      batch_create_from_tags(params[:keyword_id], params[:klass], params[:observation_matrix_id])
    when 'pinboard'
      batch_create_from_pinboard(params[:observation_matrix_id], params[:project_id], params[:user_id], params[:klass])
    end
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_tags(keyword_id, klass, observation_matrix_id)
    created = []
    ObservationMatrixRowItem.transaction do
      begin
        if klass
          klass.constantize.joins(:tags).where(tags: {keyword_id: keyword_id} ).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_tags(
            Tag.where(keyword_id: keyword_id, tag_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )       
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass)
    return false if observation_matrix_id.blank? || project_id.blank? || user_id.blank?
    created = []
    ObservationMatrixRow.transaction do
      begin
        if klass
          klass.constantize.joins(:pinboard_items).where(pinboard_items: {user_id: user_id, project_id: project_id}).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_pinboard_items(
            PinboardItem.where(project_id: project_id, user_id: user_id, pinned_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  private

  # @return [Array]
  def self.create_for_tags(tag_scope, observation_matrix_id)
    a = []
    tag_scope.each do |o|
      a.push create_for(o.tag_object, observation_matrix_id)
    end
    a
  end

  # @param pinboard_item_scope [PinboardItem Scope]
  # @return [Array]
  #   create observation matrix row items for all scope items
  def self.create_for_pinboard_items(pinboard_item_scope, observation_matrix_id)
    a = []
    pinboard_item_scope.each do |o|
      a.push create_for(o.pinned_object, observation_matrix_id)
    end
    a 
  end

  def self.create_for(object, observation_matrix_id)
    p = { observation_matrix_id: observation_matrix_id }
    case object.class.base_class.name
    when 'Otu'
      p[:otu_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleOtu'
    when 'CollectionObject'
      p[:collection_object_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleCollectionObject'
    else
      raise 
    end
    ObservationMatrixRowItem.create!(p)
  end

  def decrement_matrix_row_reference_count(mr)
    current = mr.reference_count - 1

    if current == 0
      mr.delete
    else
      mr.update_columns(reference_count: current)
      mr.update_columns(cached_observation_matrix_row_item_id: nil) if current == 1 && type =~ /Single/ # we've deleted the only single, so the last must be a Dynamic/Tagged
    end
  end

  def increment_matrix_row_reference_count(mr)
    mr.update_columns(reference_count: mr.reference_count + 1)
    mr.update_columns(cached_observation_matrix_row_item_id: id) if type =~ /Single/
  end

end

- (Integer) otu_id

Returns id of an (single) Otu based row

Returns:

  • (Integer)

    id of an (single) Otu based row



18
19
20
21
22
23
24
25
26
27
28
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
# File 'app/models/observation_matrix_row_item.rb', line 18

class ObservationMatrixRowItem < ApplicationRecord
  include Housekeeping
  include Shared::Citations
  include Shared::Identifiers
  include Shared::IsData
  include Shared::Tags
  include Shared::Notes

  acts_as_list scope: [:observation_matrix_id, :project_id]

  ALL_STI_ATTRIBUTES = [:otu_id, :collection_object_id, :controlled_vocabulary_term_id].freeze

  belongs_to :observation_matrix, inverse_of: :observation_matrix_row_items
  belongs_to :otu, inverse_of: :observation_matrix_row_items
  belongs_to :collection_object, inverse_of: :observation_matrix_row_items

  validates_presence_of :observation_matrix
  validate :type_is_subclassed
  validate :other_subclass_attributes_not_set, if: -> {!type.blank?}

  after_save :update_matrix_rows
  after_destroy :cleanup_matrix_rows

  def update_matrix_rows
    objects = Array.new
    objects.push *otus if otus
    objects.push *collection_objects if collection_objects

    objects.each do |o|
      update_single_matrix_row o
    end
  end

  def cleanup_matrix_rows
    rows = []
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: otus.map(&:id)) if otus
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: collection_objects.map(&:id)) if collection_objects

    rows.each do |mr|
      decrement_matrix_row_reference_count(mr)
    end
  end

  def update_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, otu: object )
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, collection_object: object)
    end
    increment_matrix_row_reference_count(mr)
  end

  def cleanup_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: object.id).first
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: object.id).first
    end

    decrement_matrix_row_reference_count(mr)
  end

  def self.human_name
    self.name.demodulize.humanize
  end

  # @return [Array]
  #   the otus "defined" by this matrix row item
  # override
  def otus
    false
  end

  # @return [Array]
  #   the collection objects "defined" by this matrix row item
  # override
  def collection_objects
    false
  end

  # @return [Array]
  #   the required attributes for this subclass
  # override
  def self.subclass_attributes
    []
  end

  # @return [Object]
  #   the object used to define the set of matrix rows
  # override
  def matrix_row_item_object
    nil
  end

  # @return [matrix_row_item_object, nil]
  def object_is?(object_type)
    matrix_row_item_object.class.name == object_type ? matrix_row_item_object : nil
  end

  # @return [Boolean]
  #   whether this is a dynamic or fixed class
  #   override in subclasses
  def is_dynamic?
    false
  end

  protected

  def other_subclass_attributes_not_set
    (ALL_STI_ATTRIBUTES - self.type.constantize.subclass_attributes).each do |attr|
      errors.add(attr, 'is not valid for this type of observation matrix row item') if !send(attr).blank?
    end
  end

  def type_is_subclassed
    if !MATRIX_ROW_ITEM_TYPES[type]
      errors.add(:type, 'type must be a valid subclass')
    end
  end

  # @return [Array] of ObservationMatrixRowItems
  def self.batch_create(params)
    case params[:batch_type]
    when 'tags'
      batch_create_from_tags(params[:keyword_id], params[:klass], params[:observation_matrix_id])
    when 'pinboard'
      batch_create_from_pinboard(params[:observation_matrix_id], params[:project_id], params[:user_id], params[:klass])
    end
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_tags(keyword_id, klass, observation_matrix_id)
    created = []
    ObservationMatrixRowItem.transaction do
      begin
        if klass
          klass.constantize.joins(:tags).where(tags: {keyword_id: keyword_id} ).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_tags(
            Tag.where(keyword_id: keyword_id, tag_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )       
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass)
    return false if observation_matrix_id.blank? || project_id.blank? || user_id.blank?
    created = []
    ObservationMatrixRow.transaction do
      begin
        if klass
          klass.constantize.joins(:pinboard_items).where(pinboard_items: {user_id: user_id, project_id: project_id}).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_pinboard_items(
            PinboardItem.where(project_id: project_id, user_id: user_id, pinned_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  private

  # @return [Array]
  def self.create_for_tags(tag_scope, observation_matrix_id)
    a = []
    tag_scope.each do |o|
      a.push create_for(o.tag_object, observation_matrix_id)
    end
    a
  end

  # @param pinboard_item_scope [PinboardItem Scope]
  # @return [Array]
  #   create observation matrix row items for all scope items
  def self.create_for_pinboard_items(pinboard_item_scope, observation_matrix_id)
    a = []
    pinboard_item_scope.each do |o|
      a.push create_for(o.pinned_object, observation_matrix_id)
    end
    a 
  end

  def self.create_for(object, observation_matrix_id)
    p = { observation_matrix_id: observation_matrix_id }
    case object.class.base_class.name
    when 'Otu'
      p[:otu_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleOtu'
    when 'CollectionObject'
      p[:collection_object_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleCollectionObject'
    else
      raise 
    end
    ObservationMatrixRowItem.create!(p)
  end

  def decrement_matrix_row_reference_count(mr)
    current = mr.reference_count - 1

    if current == 0
      mr.delete
    else
      mr.update_columns(reference_count: current)
      mr.update_columns(cached_observation_matrix_row_item_id: nil) if current == 1 && type =~ /Single/ # we've deleted the only single, so the last must be a Dynamic/Tagged
    end
  end

  def increment_matrix_row_reference_count(mr)
    mr.update_columns(reference_count: mr.reference_count + 1)
    mr.update_columns(cached_observation_matrix_row_item_id: id) if type =~ /Single/
  end

end

- (Integer) position

Returns a sort order

Returns:

  • (Integer)

    a sort order



18
19
20
21
22
23
24
25
26
27
28
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
# File 'app/models/observation_matrix_row_item.rb', line 18

class ObservationMatrixRowItem < ApplicationRecord
  include Housekeeping
  include Shared::Citations
  include Shared::Identifiers
  include Shared::IsData
  include Shared::Tags
  include Shared::Notes

  acts_as_list scope: [:observation_matrix_id, :project_id]

  ALL_STI_ATTRIBUTES = [:otu_id, :collection_object_id, :controlled_vocabulary_term_id].freeze

  belongs_to :observation_matrix, inverse_of: :observation_matrix_row_items
  belongs_to :otu, inverse_of: :observation_matrix_row_items
  belongs_to :collection_object, inverse_of: :observation_matrix_row_items

  validates_presence_of :observation_matrix
  validate :type_is_subclassed
  validate :other_subclass_attributes_not_set, if: -> {!type.blank?}

  after_save :update_matrix_rows
  after_destroy :cleanup_matrix_rows

  def update_matrix_rows
    objects = Array.new
    objects.push *otus if otus
    objects.push *collection_objects if collection_objects

    objects.each do |o|
      update_single_matrix_row o
    end
  end

  def cleanup_matrix_rows
    rows = []
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: otus.map(&:id)) if otus
    rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: collection_objects.map(&:id)) if collection_objects

    rows.each do |mr|
      decrement_matrix_row_reference_count(mr)
    end
  end

  def update_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, otu: object )
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, collection_object: object)
    end
    increment_matrix_row_reference_count(mr)
  end

  def cleanup_single_matrix_row(object)
    mr = nil

    if object.is_a? Otu
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: object.id).first
    elsif object.is_a? CollectionObject
      mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: object.id).first
    end

    decrement_matrix_row_reference_count(mr)
  end

  def self.human_name
    self.name.demodulize.humanize
  end

  # @return [Array]
  #   the otus "defined" by this matrix row item
  # override
  def otus
    false
  end

  # @return [Array]
  #   the collection objects "defined" by this matrix row item
  # override
  def collection_objects
    false
  end

  # @return [Array]
  #   the required attributes for this subclass
  # override
  def self.subclass_attributes
    []
  end

  # @return [Object]
  #   the object used to define the set of matrix rows
  # override
  def matrix_row_item_object
    nil
  end

  # @return [matrix_row_item_object, nil]
  def object_is?(object_type)
    matrix_row_item_object.class.name == object_type ? matrix_row_item_object : nil
  end

  # @return [Boolean]
  #   whether this is a dynamic or fixed class
  #   override in subclasses
  def is_dynamic?
    false
  end

  protected

  def other_subclass_attributes_not_set
    (ALL_STI_ATTRIBUTES - self.type.constantize.subclass_attributes).each do |attr|
      errors.add(attr, 'is not valid for this type of observation matrix row item') if !send(attr).blank?
    end
  end

  def type_is_subclassed
    if !MATRIX_ROW_ITEM_TYPES[type]
      errors.add(:type, 'type must be a valid subclass')
    end
  end

  # @return [Array] of ObservationMatrixRowItems
  def self.batch_create(params)
    case params[:batch_type]
    when 'tags'
      batch_create_from_tags(params[:keyword_id], params[:klass], params[:observation_matrix_id])
    when 'pinboard'
      batch_create_from_pinboard(params[:observation_matrix_id], params[:project_id], params[:user_id], params[:klass])
    end
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_tags(keyword_id, klass, observation_matrix_id)
    created = []
    ObservationMatrixRowItem.transaction do
      begin
        if klass
          klass.constantize.joins(:tags).where(tags: {keyword_id: keyword_id} ).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_tags(
            Tag.where(keyword_id: keyword_id, tag_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )       
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  # @params klass [String] the class name like `Otu` or `CollectionObject`
  # @return [Array, false]
  def self.batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass)
    return false if observation_matrix_id.blank? || project_id.blank? || user_id.blank?
    created = []
    ObservationMatrixRow.transaction do
      begin
        if klass
          klass.constantize.joins(:pinboard_items).where(pinboard_items: {user_id: user_id, project_id: project_id}).each do |o|
            created.push create_for(o, observation_matrix_id)
          end
        else
          created += create_for_pinboard_items(
            PinboardItem.where(project_id: project_id, user_id: user_id, pinned_object_type: ['Otu', 'CollectionObject']).all,
            observation_matrix_id
          )
        end
      rescue ActiveRecord::RecordInvalid => e
        return false
      end
    end
    return created
  end

  private

  # @return [Array]
  def self.create_for_tags(tag_scope, observation_matrix_id)
    a = []
    tag_scope.each do |o|
      a.push create_for(o.tag_object, observation_matrix_id)
    end
    a
  end

  # @param pinboard_item_scope [PinboardItem Scope]
  # @return [Array]
  #   create observation matrix row items for all scope items
  def self.create_for_pinboard_items(pinboard_item_scope, observation_matrix_id)
    a = []
    pinboard_item_scope.each do |o|
      a.push create_for(o.pinned_object, observation_matrix_id)
    end
    a 
  end

  def self.create_for(object, observation_matrix_id)
    p = { observation_matrix_id: observation_matrix_id }
    case object.class.base_class.name
    when 'Otu'
      p[:otu_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleOtu'
    when 'CollectionObject'
      p[:collection_object_id] = object.id
      p[:type] = 'ObservationMatrixRowItem::SingleCollectionObject'
    else
      raise 
    end
    ObservationMatrixRowItem.create!(p)
  end

  def decrement_matrix_row_reference_count(mr)
    current = mr.reference_count - 1

    if current == 0
      mr.delete
    else
      mr.update_columns(reference_count: current)
      mr.update_columns(cached_observation_matrix_row_item_id: nil) if current == 1 && type =~ /Single/ # we've deleted the only single, so the last must be a Dynamic/Tagged
    end
  end

  def increment_matrix_row_reference_count(mr)
    mr.update_columns(reference_count: mr.reference_count + 1)
    mr.update_columns(cached_observation_matrix_row_item_id: id) if type =~ /Single/
  end

end

Class Method Details

+ (Array) batch_create(params) (protected)

Returns of ObservationMatrixRowItems

Returns:

  • (Array)

    of ObservationMatrixRowItems



143
144
145
146
147
148
149
150
# File 'app/models/observation_matrix_row_item.rb', line 143

def self.batch_create(params)
  case params[:batch_type]
  when 'tags'
    batch_create_from_tags(params[:keyword_id], params[:klass], params[:observation_matrix_id])
  when 'pinboard'
    batch_create_from_pinboard(params[:observation_matrix_id], params[:project_id], params[:user_id], params[:klass])
  end
end

+ (Array, false) batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass) (protected)

Returns:

  • (Array, false)


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'app/models/observation_matrix_row_item.rb', line 177

def self.batch_create_from_pinboard(observation_matrix_id, project_id, user_id, klass)
  return false if observation_matrix_id.blank? || project_id.blank? || user_id.blank?
  created = []
  ObservationMatrixRow.transaction do
    begin
      if klass
        klass.constantize.joins(:pinboard_items).where(pinboard_items: {user_id: user_id, project_id: project_id}).each do |o|
          created.push create_for(o, observation_matrix_id)
        end
      else
        created += create_for_pinboard_items(
          PinboardItem.where(project_id: project_id, user_id: user_id, pinned_object_type: ['Otu', 'CollectionObject']).all,
          observation_matrix_id
        )
      end
    rescue ActiveRecord::RecordInvalid => e
      return false
    end
  end
  return created
end

+ (Array, false) batch_create_from_tags(keyword_id, klass, observation_matrix_id) (protected)

Returns:

  • (Array, false)


154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'app/models/observation_matrix_row_item.rb', line 154

def self.batch_create_from_tags(keyword_id, klass, observation_matrix_id)
  created = []
  ObservationMatrixRowItem.transaction do
    begin
      if klass
        klass.constantize.joins(:tags).where(tags: {keyword_id: keyword_id} ).each do |o|
          created.push create_for(o, observation_matrix_id)
        end
      else
        created += create_for_tags(
          Tag.where(keyword_id: keyword_id, tag_object_type: ['Otu', 'CollectionObject']).all,
          observation_matrix_id
        )       
      end
    rescue ActiveRecord::RecordInvalid => e
      return false
    end
  end
  return created
end

+ (Object) create_for(object, observation_matrix_id) (private)



221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'app/models/observation_matrix_row_item.rb', line 221

def self.create_for(object, observation_matrix_id)
  p = { observation_matrix_id: observation_matrix_id }
  case object.class.base_class.name
  when 'Otu'
    p[:otu_id] = object.id
    p[:type] = 'ObservationMatrixRowItem::SingleOtu'
  when 'CollectionObject'
    p[:collection_object_id] = object.id
    p[:type] = 'ObservationMatrixRowItem::SingleCollectionObject'
  else
    raise 
  end
  ObservationMatrixRowItem.create!(p)
end

+ (Array) create_for_pinboard_items(pinboard_item_scope, observation_matrix_id) (private)

Returns create observation matrix row items for all scope items

Parameters:

Returns:

  • (Array)

    create observation matrix row items for all scope items



213
214
215
216
217
218
219
# File 'app/models/observation_matrix_row_item.rb', line 213

def self.create_for_pinboard_items(pinboard_item_scope, observation_matrix_id)
  a = []
  pinboard_item_scope.each do |o|
    a.push create_for(o.pinned_object, observation_matrix_id)
  end
  a 
end

+ (Array) create_for_tags(tag_scope, observation_matrix_id) (private)

Returns:

  • (Array)


202
203
204
205
206
207
208
# File 'app/models/observation_matrix_row_item.rb', line 202

def self.create_for_tags(tag_scope, observation_matrix_id)
  a = []
  tag_scope.each do |o|
    a.push create_for(o.tag_object, observation_matrix_id)
  end
  a
end

+ (Object) human_name



84
85
86
# File 'app/models/observation_matrix_row_item.rb', line 84

def self.human_name
  self.name.demodulize.humanize
end

+ (Array) subclass_attributes

override

Returns:

  • (Array)

    the required attributes for this subclass



105
106
107
# File 'app/models/observation_matrix_row_item.rb', line 105

def self.subclass_attributes
  []
end

Instance Method Details

- (Object) cleanup_matrix_rows



51
52
53
54
55
56
57
58
59
# File 'app/models/observation_matrix_row_item.rb', line 51

def cleanup_matrix_rows
  rows = []
  rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: otus.map(&:id)) if otus
  rows.push *ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: collection_objects.map(&:id)) if collection_objects

  rows.each do |mr|
    decrement_matrix_row_reference_count(mr)
  end
end

- (Object) cleanup_single_matrix_row(object)



72
73
74
75
76
77
78
79
80
81
82
# File 'app/models/observation_matrix_row_item.rb', line 72

def cleanup_single_matrix_row(object)
  mr = nil

  if object.is_a? Otu
    mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, otu_id: object.id).first
  elsif object.is_a? CollectionObject
    mr = ObservationMatrixRow.where(observation_matrix: observation_matrix, collection_object_id: object.id).first
  end

  decrement_matrix_row_reference_count(mr)
end

- (Array) collection_objects

override

Returns:

  • (Array)

    the collection objects “defined” by this matrix row item



98
99
100
# File 'app/models/observation_matrix_row_item.rb', line 98

def collection_objects
  false
end

- (Object) decrement_matrix_row_reference_count(mr) (private)



236
237
238
239
240
241
242
243
244
245
# File 'app/models/observation_matrix_row_item.rb', line 236

def decrement_matrix_row_reference_count(mr)
  current = mr.reference_count - 1

  if current == 0
    mr.delete
  else
    mr.update_columns(reference_count: current)
    mr.update_columns(cached_observation_matrix_row_item_id: nil) if current == 1 && type =~ /Single/ # we've deleted the only single, so the last must be a Dynamic/Tagged
  end
end

- (Object) increment_matrix_row_reference_count(mr) (private)



247
248
249
250
# File 'app/models/observation_matrix_row_item.rb', line 247

def increment_matrix_row_reference_count(mr)
  mr.update_columns(reference_count: mr.reference_count + 1)
  mr.update_columns(cached_observation_matrix_row_item_id: id) if type =~ /Single/
end

- (Boolean) is_dynamic?

Returns whether this is a dynamic or fixed class override in subclasses

Returns:

  • (Boolean)

    whether this is a dynamic or fixed class override in subclasses



124
125
126
# File 'app/models/observation_matrix_row_item.rb', line 124

def is_dynamic?
  false
end

- (Object) matrix_row_item_object

override

Returns:

  • (Object)

    the object used to define the set of matrix rows



112
113
114
# File 'app/models/observation_matrix_row_item.rb', line 112

def matrix_row_item_object
  nil
end

- (matrix_row_item_object?) object_is?(object_type)

Returns:

  • (matrix_row_item_object, nil)


117
118
119
# File 'app/models/observation_matrix_row_item.rb', line 117

def object_is?(object_type)
  matrix_row_item_object.class.name == object_type ? matrix_row_item_object : nil
end

- (Object) other_subclass_attributes_not_set (protected)



130
131
132
133
134
# File 'app/models/observation_matrix_row_item.rb', line 130

def other_subclass_attributes_not_set
  (ALL_STI_ATTRIBUTES - self.type.constantize.subclass_attributes).each do |attr|
    errors.add(attr, 'is not valid for this type of observation matrix row item') if !send(attr).blank?
  end
end

- (Array) otus

override

Returns:

  • (Array)

    the otus “defined” by this matrix row item



91
92
93
# File 'app/models/observation_matrix_row_item.rb', line 91

def otus
  false
end

- (Object) type_is_subclassed (protected)



136
137
138
139
140
# File 'app/models/observation_matrix_row_item.rb', line 136

def type_is_subclassed
  if !MATRIX_ROW_ITEM_TYPES[type]
    errors.add(:type, 'type must be a valid subclass')
  end
end

- (Object) update_matrix_rows



41
42
43
44
45
46
47
48
49
# File 'app/models/observation_matrix_row_item.rb', line 41

def update_matrix_rows
  objects = Array.new
  objects.push *otus if otus
  objects.push *collection_objects if collection_objects

  objects.each do |o|
    update_single_matrix_row o
  end
end

- (Object) update_single_matrix_row(object)



61
62
63
64
65
66
67
68
69
70
# File 'app/models/observation_matrix_row_item.rb', line 61

def update_single_matrix_row(object)
  mr = nil

  if object.is_a? Otu
    mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, otu: object )
  elsif object.is_a? CollectionObject
    mr = ObservationMatrixRow.find_or_create_by(observation_matrix: observation_matrix, collection_object: object)
  end
  increment_matrix_row_reference_count(mr)
end