Class: Sample

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
ActionView::Helpers::DateHelper, FieldValuer, SampleValidator
Defined in:
app/models/sample.rb

Overview

A named, biologically unique definition for an instance of a SampleType, such as a specific Primer, Fragment, Plasmid, or Yeast Strain A Sample has many Items in inventory

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.creator(raw, user) ⇒ Object

Examples:

Create a new primer

s = Sample.creator(
  {
    sample_type_id: SampleType.find_by_name("Primer").id,
    description: "This is a test",
    name: "Yet Another Primer Test",
    project: "Auxin",
    field_values: [
      { name: "Anneal Sequence", value: "ATTCTA" },
      { name: "Overhang Sequence", value: "ATCTCGAGCT" },
      { name: "T Anneal", value: 70 }
    ]
  }, User.find(1))

  s.errors.any?


65
66
67
68
69
70
71
72
# File 'app/models/sample.rb', line 65

def self.creator(raw, user)
  sample = Sample.new
  sample.user_id = user.id
  sample.sample_type_id = raw[:sample_type_id]
  sample.updater raw

  sample
end

.for_project(project:) ⇒ Object



240
241
242
# File 'app/models/sample.rb', line 240

def self.for_project(project:)
  where(project: project)
end

.okay_to_drop?(sample, user) ⇒ Boolean

Returns:

  • (Boolean)


207
208
209
210
211
212
213
214
215
# File 'app/models/sample.rb', line 207

def self.okay_to_drop?(sample, user)

  warn('Could not find sample')                                                && (return false) unless sample
  warn("Not allowed to delete sample #{sample.id}")                            && (return false) unless sample.user_id == user.id
  warn("Could not delete sample #{sample.id} because it has associated items") && (return false) unless sample.items.empty?

  true

end

.owned_by(user:) ⇒ Object



244
245
246
# File 'app/models/sample.rb', line 244

def self.owned_by(user:)
  where(user_id: user.id)
end

.sample_from_identifier(str) ⇒ Object



43
44
45
46
47
48
# File 'app/models/sample.rb', line 43

def self.sample_from_identifier(str)
  return unless str

  parts = str.split(': ')
  Sample.find_by(name: parts[1..-1].join(': ')) if parts.length > 1
end

.with_sample_type(sample_type:) ⇒ Object

scopes for searching Samples



236
237
238
# File 'app/models/sample.rb', line 236

def self.with_sample_type(sample_type:)
  where(sample_type_id: sample_type.id)
end

Instance Method Details

#data_hashObject



217
218
219
# File 'app/models/sample.rb', line 217

def data_hash
  JSON.parse(data, symbolize_names: true)
end

#full_jsonObject



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

def full_json

  sample_hash = as_json(
    include: { sample_type: { include: :object_types, methods: :field_types } },
    methods: :full_field_values
  )

  # rename field for compatibility with ng-control/sample.js
  sample_hash['field_values'] = sample_hash.delete 'full_field_values'

  sample_hash

end

#in(container) ⇒ Array<Item>

Deprecated.

use Item query

Return all items of this Sample in the provided ObjectType.

Examples:

find a 1 kb ladder for gel electrophoresis

ladder_1k = Sample.find_by_name("1 kb Ladder").in("Ladder Aliquot")

Parameters:

Returns:



159
160
161
162
163
164
165
166
167
168
# File 'app/models/sample.rb', line 159

def in(container)

  c = ObjectType.find_by name: container
  if c
    Item.with_sample(sample: this).where(object_type: c).reject(&:deleted?)
  else
    []
  end

end

#make_item(object_type_name) ⇒ Item

Make a new Item out of this sample, with some object type.

Parameters:

  • object_type_name (String)

    describes the object type that will be used to make a new Item

Returns:

  • (Item)

    an item associated with this sample and in the container described by object_type_name The location of the item is determined by the location wizard



194
195
196
197
198
199
200
201
# File 'app/models/sample.rb', line 194

def make_item(object_type_name)

  ot = ObjectType.find_by(name: object_type_name)
  raise "Could not find object type #{name}" unless ot

  Item.make({ quantity: 1, inuse: 0 }, sample: self, object_type: ot)

end

#nameString

Gets the name of Sample.

Returns:

  • (String)

    the name of the Sample. For example, a sample whose SampleType is "Plasmid" might be named "pLAB1"



25
# File 'app/models/sample.rb', line 25

attr_accessible :name

#num_postsObject



203
204
205
# File 'app/models/sample.rb', line 203

def num_posts
  post_associations.count
end

#ownerUser

Get User who owns this Sample.

Returns:

  • (User)


177
178
179
180
181
182
183
184
# File 'app/models/sample.rb', line 177

def owner
  u = User.find_by(id: user_id)
  if u
    u.
  else
    '?'
  end
end

#parent_typeObject

interface with FieldValuer



14
15
16
# File 'app/models/sample.rb', line 14

def parent_type # interface with FieldValuer
  sample_type
end

#sample_type_idFixnum

Gets the SampleType id of sample.

Returns:

  • (Fixnum)

    id referring to the SampleType of which this sample is an instance of



30
# File 'app/models/sample.rb', line 30

attr_accessible :sample_type_id

#stringify_errors(elist) ⇒ Object



74
75
76
# File 'app/models/sample.rb', line 74

def stringify_errors(elist)
  elist.full_messages.join(',')
end

#to_sObject



170
171
172
# File 'app/models/sample.rb', line 170

def to_s
  "<a href='/samples/#{id}' class='aquarium-item' id='#{id}'>#{id}</a>"
end

#updater(raw, user = nil) ⇒ Object



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
# File 'app/models/sample.rb', line 78

def updater(raw, user = nil)
  self.name = raw[:name]
  self.description = raw[:description]
  self.project = raw[:project]

  Sample.transaction do
    save
    raise ActiveRecord::Rollback unless errors.empty?

    sample_type = SampleType.find(raw[:sample_type_id])
    if raw[:field_values]

      raw[:field_values].each do |raw_fv|

        ft = sample_type.type(raw_fv[:name])

        if ft && raw_fv[:id] && raw_fv[:deleted]

          fv = FieldValue.find_by(id: raw_fv[:id])
          fv.destroy if fv

        elsif ft && !raw_fv[:deleted] # fv might have been made and marked deleted without ever having been saved

          if raw_fv[:id]
            begin
              fv = FieldValue.find(raw_fv[:id])
            rescue ActiveRecord::RecordNotFound => e
              errors.add :missing_field_value, "Field value #{raw_fv[:id]} not found in db."
              errors.add :missing_field_value, e.to_s
              raise ActiveRecord::Rollback
            end
          else
            fv = field_values.create(name: raw_fv[:name])
          end

          if ft.sample?
            child = if raw_fv[:new_child_sample]
                      Sample.creator(raw_fv[:new_child_sample], user || User.find(user_id))
                    else
                      Sample.sample_from_identifier raw_fv[:child_sample_name]
                    end
            fv.child_sample_id = child.id if child
            fv.child_sample_id = nil if !child && raw_fv[:child_sample_name] == ''
            if !child && ft.required && raw_fv[:child_sample_name] != ''
              errors.add :required, "Sample required for field '#{ft.name}' not found or not specified."
              raise ActiveRecord::Rollback
            end
            unless !child || child.errors.empty?
              errors.add :child_error, "#{ft.name}: " + stringify_errors(child.errors)
              raise ActiveRecord::Rollback
            end
          elsif ft.number?
            fv.value = raw_fv[:value].to_f
          else # string, url
            fv.value = raw_fv[:value]
          end

          puts "before fv saved: #{fv.inspect}"
          fv.save
          puts "fv saved. now #{fv.inspect}"

          unless fv.errors.empty?
            errors.add :field_value, "Could not save field #{raw_fv[:name]}: #{stringify_errors(fv.errors)}"
            raise ActiveRecord::Rollback
          end

        end # if

      end # each

    end # if

  end
end