Module: StudySubjectIdentifier
- Included in:
- StudySubject
- Defined in:
- app/models/study_subject_identifier.rb
Overview
Simply extracted some code to clean up model. I’d like to do this to all of the really big classes but let’s see how this goes first.
Class Method Summary collapse
Class Method Details
.included(base) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 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 |
# File 'app/models/study_subject_identifier.rb', line 7 def self.included(base) # Must delay the calls to these ActiveRecord methods # or it will raise many "undefined method"s. base.class_eval do # Very cool that this doesn't stop factory girl from using them. # it will stop the study_subject nested_attribute tests though attr_protected :studyid, :studyid_nohyphen, :studyid_intonly_nohyphen, :familyid, :childid, :subjectid, :patid, :orderno before_validation :prepare_fields_for_validation before_create :prepare_fields_for_creation def self.find_all_by_studyid_or_icf_master_id(studyid,icf_master_id) # if decide to use LIKE, will need to NOT include nils so # will need to add some conditions to the conditions. self.find( :all, :conditions => [ "studyid = :studyid OR icf_master_id = :icf_master_id", { :studyid => studyid, :icf_master_id => icf_master_id } ] ) end protected def prepare_fields_for_validation # NOTE ANY field that has a unique index in the database NEEDS # to NOT be blank. Multiple nils are acceptable in index, # but multiple blanks are NOT. Nilify ALL fields with # unique indexes in the database. self.email = nil if email.blank? self.ssn = nil if ssn.blank? self.state_id_no = nil if state_id_no.blank? self.state_registrar_no = nil if state_registrar_no.blank? self.local_registrar_no = nil if local_registrar_no.blank? self.gbid = nil if gbid.blank? self.lab_no_wiemels = nil if lab_no_wiemels.blank? self.accession_no = nil if accession_no.blank? self.idno_wiemels = nil if idno_wiemels.blank? self.case_control_type = ( ( case_control_type.blank? ) ? nil : case_control_type.to_s.upcase ) patid.try(:gsub!,/\D/,'') self.patid = sprintf("%04d",patid.to_i) unless patid.blank? matchingid.try(:gsub!,/\D/,'') # TODO add more tests for this (try with valid? method) #puts "Matchingid before before validation:#{matchingid}" self.matchingid = sprintf("%06d",matchingid.to_i) unless matchingid.blank? end # made separate method so can be stubbed def get_next_childid self.class.maximum(:childid).to_i + 1 end # made separate method so can be stubbed def get_next_patid self.class.maximum(:patid).to_i + 1 # # What happens if/when this goes over 4 digits? # The database field is only 4 chars. # end # fields made from fields that WON'T change go here def prepare_fields_for_creation # don't assign if given or is mother (childid is currently protected) self.childid = get_next_childid if !is_mother? and childid.blank? # don't assign if given or is not case (patid is currently protected) self.patid = sprintf("%04d",get_next_patid.to_i) if is_case? and patid.blank? # should move this from pre validation to here for ALL subjects. # patid.try(:gsub!,/\D/,'') # self.patid = sprintf("%04d",patid.to_i) unless patid.blank? # don't assign if given or is not case (orderno is currently protected) self.orderno = 0 if is_case? and orderno.blank? # don't assign if given or is mother (studyid is currently protected) # or if can't make complete studyid if !is_mother? and studyid.blank? and !patid.blank? and !case_control_type.blank? and !orderno.blank? self.studyid = "#{patid}-#{case_control_type}-#{orderno}" end # perhaps put in an after_save with an update_attribute(s) # and simply generate a new one until all is well # don't assign if given (subjectid is currently protected) self.subjectid = generate_subjectid if subjectid.blank? # cases and controls: their own subjectID is also their familyID. # mothers: their child's subjectID is their familyID. That is, # a mother and her child have identical familyIDs. # don't assign if given (familyid is currently protected) self.familyid = subjectid if !is_mother? and familyid.blank? # cases (patients): matchingID is the study_subject's own subjectID # controls: matchingID is subjectID of the associated case # (like PatID in this respect). # mothers: matchingID is subjectID of their own child's associated case. # That is, a mother's matchingID is the same as their child's. This # will become clearer when I provide specs for mother study_subject creation. # matchingid is manually set in some tests. will need to setup for stubbing this. # don't assign if given (matchingid is currently NOT protected) self.matchingid = subjectid if is_case? and matchingid.blank? end # made separate method so can stub it in testing # This only guarantees uniqueness before creation, # but not at creation. This is NOT scalable. # Fortunately, we won't be creating tons of study_subjects # at the same time so this should not be an issue, # however, when it fails, it will be confusing. # TODO # How to rescue from ActiveRecord::RecordInvalid here? # or would it be RecordNotSaved? # # Perhaps treat subjectid like icf_master_id? # Create a table with all of the possible # subjectid ... (1..999999) # study_subject_id # assigned_on # Then select a random unassigned one? # Would this be faster? # def generate_subjectid subjectids = ( (1..999999).to_a - self.class.find(:all,:select => 'subjectid' ).collect(&:subjectid).collect(&:to_i) ) # CANNOT have leading 0' as it thinks its octal and converts #>> sprintf("%06d","0001234") #=> "000668" # # CANNOT have leading 0's and include and 8 or 9 as it thinks its octal # so convert back to Integer first #>> sprintf("%06d","0001280") #ArgumentError: invalid value for Integer: "0001280" # from (irb):24:in `sprintf' # from (irb):24 sprintf("%06d",subjectids[rand(subjectids.length)].to_i) end end # class_eval end |