ccls-ccls_engine 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. data/README.rdoc +182 -0
  2. data/app/models/abstract.rb +181 -0
  3. data/app/models/abstract_search.rb +50 -0
  4. data/app/models/abstract_validations.rb +324 -0
  5. data/app/models/address.rb +70 -0
  6. data/app/models/address_type.rb +15 -0
  7. data/app/models/addressing.rb +147 -0
  8. data/app/models/aliquot.rb +44 -0
  9. data/app/models/aliquot_sample_format.rb +13 -0
  10. data/app/models/analysis.rb +14 -0
  11. data/app/models/bc_request.rb +20 -0
  12. data/app/models/candidate_control.rb +101 -0
  13. data/app/models/context.rb +23 -0
  14. data/app/models/context_data_source.rb +4 -0
  15. data/app/models/county.rb +16 -0
  16. data/app/models/data_source.rb +24 -0
  17. data/app/models/diagnosis.rb +23 -0
  18. data/app/models/document_type.rb +16 -0
  19. data/app/models/document_version.rb +27 -0
  20. data/app/models/enrollment.rb +78 -0
  21. data/app/models/enrollment_validations.rb +167 -0
  22. data/app/models/follow_up.rb +16 -0
  23. data/app/models/follow_up_type.rb +18 -0
  24. data/app/models/gift_card.rb +22 -0
  25. data/app/models/gift_card_search.rb +137 -0
  26. data/app/models/home_exposure_response.rb +24 -0
  27. data/app/models/homex_outcome.rb +75 -0
  28. data/app/models/hospital.rb +22 -0
  29. data/app/models/icf_master_id.rb +30 -0
  30. data/app/models/icf_master_tracker.rb +217 -0
  31. data/app/models/icf_master_tracker_change.rb +9 -0
  32. data/app/models/icf_master_tracker_update.rb +50 -0
  33. data/app/models/ineligible_reason.rb +26 -0
  34. data/app/models/instrument.rb +26 -0
  35. data/app/models/instrument_type.rb +17 -0
  36. data/app/models/instrument_version.rb +28 -0
  37. data/app/models/interview.rb +122 -0
  38. data/app/models/interview_method.rb +17 -0
  39. data/app/models/interview_outcome.rb +16 -0
  40. data/app/models/language.rb +28 -0
  41. data/app/models/live_birth_data_update.rb +142 -0
  42. data/app/models/operational_event.rb +99 -0
  43. data/app/models/operational_event_type.rb +31 -0
  44. data/app/models/organization.rb +28 -0
  45. data/app/models/patient.rb +63 -0
  46. data/app/models/patient_validations.rb +118 -0
  47. data/app/models/person.rb +28 -0
  48. data/app/models/phone_number.rb +105 -0
  49. data/app/models/phone_type.rb +15 -0
  50. data/app/models/project.rb +39 -0
  51. data/app/models/project_outcome.rb +19 -0
  52. data/app/models/race.rb +31 -0
  53. data/app/models/refusal_reason.rb +23 -0
  54. data/app/models/sample.rb +168 -0
  55. data/app/models/sample_kit.rb +14 -0
  56. data/app/models/sample_outcome.rb +16 -0
  57. data/app/models/sample_temperature.rb +14 -0
  58. data/app/models/sample_type.rb +37 -0
  59. data/app/models/search.rb +195 -0
  60. data/app/models/section.rb +18 -0
  61. data/app/models/state.rb +25 -0
  62. data/app/models/study_subject.rb +237 -0
  63. data/app/models/study_subject_abstracts.rb +47 -0
  64. data/app/models/study_subject_addresses.rb +34 -0
  65. data/app/models/study_subject_associations.rb +38 -0
  66. data/app/models/study_subject_duplicates.rb +111 -0
  67. data/app/models/study_subject_enrollments.rb +17 -0
  68. data/app/models/study_subject_homex_outcome.rb +22 -0
  69. data/app/models/study_subject_identifier.rb +153 -0
  70. data/app/models/study_subject_interviews.rb +25 -0
  71. data/app/models/study_subject_languages.rb +21 -0
  72. data/app/models/study_subject_operational_events.rb +66 -0
  73. data/app/models/study_subject_patient.rb +177 -0
  74. data/app/models/study_subject_pii.rb +74 -0
  75. data/app/models/study_subject_races.rb +25 -0
  76. data/app/models/study_subject_search.rb +260 -0
  77. data/app/models/study_subject_validations.rb +116 -0
  78. data/app/models/subject_language.rb +11 -0
  79. data/app/models/subject_race.rb +11 -0
  80. data/app/models/subject_relationship.rb +21 -0
  81. data/app/models/subject_type.rb +22 -0
  82. data/app/models/tracing_status.rb +20 -0
  83. data/app/models/transfer.rb +40 -0
  84. data/app/models/unit.rb +14 -0
  85. data/app/models/vital_status.rb +19 -0
  86. data/app/models/zip_code.rb +36 -0
  87. data/config/abstract_fields.yml +1038 -0
  88. data/config/abstract_sections.yml +77 -0
  89. data/config/home_exposure_response_fields.yml +583 -0
  90. data/config/icf_master_tracker_update.yml +56 -0
  91. data/config/live_birth_data_update.yml +56 -0
  92. data/config/shared_use_db.yml +4 -0
  93. data/generators/ccls_engine/USAGE +2 -0
  94. data/generators/ccls_engine/ccls_engine_generator.rb +123 -0
  95. data/generators/ccls_engine/templates/autotest_ccls_engine.rb +3 -0
  96. data/generators/ccls_engine/templates/ccls_engine.rake +12 -0
  97. data/generators/ccls_engine/templates/fixtures/address_types.yml +30 -0
  98. data/generators/ccls_engine/templates/fixtures/context_data_sources.yml +54 -0
  99. data/generators/ccls_engine/templates/fixtures/contexts.yml +19 -0
  100. data/generators/ccls_engine/templates/fixtures/data_sources.yml +40 -0
  101. data/generators/ccls_engine/templates/fixtures/diagnoses.yml +40 -0
  102. data/generators/ccls_engine/templates/fixtures/document_types.yml +65 -0
  103. data/generators/ccls_engine/templates/fixtures/document_versions.csv +155 -0
  104. data/generators/ccls_engine/templates/fixtures/follow_up_types.yml +16 -0
  105. data/generators/ccls_engine/templates/fixtures/hospitals.yml +114 -0
  106. data/generators/ccls_engine/templates/fixtures/ineligible_reasons.yml +35 -0
  107. data/generators/ccls_engine/templates/fixtures/instrument_types.yml +26 -0
  108. data/generators/ccls_engine/templates/fixtures/instrument_versions.yml +22 -0
  109. data/generators/ccls_engine/templates/fixtures/instruments.yml +22 -0
  110. data/generators/ccls_engine/templates/fixtures/interview_methods.yml +30 -0
  111. data/generators/ccls_engine/templates/fixtures/interview_outcomes.yml +31 -0
  112. data/generators/ccls_engine/templates/fixtures/languages.yml +34 -0
  113. data/generators/ccls_engine/templates/fixtures/operational_event_types.yml +141 -0
  114. data/generators/ccls_engine/templates/fixtures/organizations.yml +198 -0
  115. data/generators/ccls_engine/templates/fixtures/people.yml +130 -0
  116. data/generators/ccls_engine/templates/fixtures/phone_types.yml +30 -0
  117. data/generators/ccls_engine/templates/fixtures/project_outcomes.yml +25 -0
  118. data/generators/ccls_engine/templates/fixtures/projects.yml +59 -0
  119. data/generators/ccls_engine/templates/fixtures/races.yml +52 -0
  120. data/generators/ccls_engine/templates/fixtures/refusal_reasons.yml +55 -0
  121. data/generators/ccls_engine/templates/fixtures/sample_outcomes.yml +36 -0
  122. data/generators/ccls_engine/templates/fixtures/sample_temperatures.yml +16 -0
  123. data/generators/ccls_engine/templates/fixtures/sample_types.yml +147 -0
  124. data/generators/ccls_engine/templates/fixtures/sections.yml +31 -0
  125. data/generators/ccls_engine/templates/fixtures/states.yml +363 -0
  126. data/generators/ccls_engine/templates/fixtures/subject_relationships.yml +46 -0
  127. data/generators/ccls_engine/templates/fixtures/subject_types.yml +30 -0
  128. data/generators/ccls_engine/templates/fixtures/tracing_statuses.yml +30 -0
  129. data/generators/ccls_engine/templates/fixtures/units.yml +13 -0
  130. data/generators/ccls_engine/templates/fixtures/vital_statuses.yml +28 -0
  131. data/generators/ccls_engine/templates/functional/roles_controller_test.rb +142 -0
  132. data/generators/ccls_engine/templates/functional/sessions_controller_test.rb +19 -0
  133. data/generators/ccls_engine/templates/functional/users_controller_test.rb +94 -0
  134. data/generators/ccls_engine/templates/images/sort_down.png +0 -0
  135. data/generators/ccls_engine/templates/images/sort_up.png +0 -0
  136. data/generators/ccls_engine/templates/initializer.rb +28 -0
  137. data/generators/ccls_engine/templates/javascripts/ccls_engine.js +24 -0
  138. data/generators/ccls_engine/templates/javascripts/jquery-ui.js +763 -0
  139. data/generators/ccls_engine/templates/javascripts/jquery.js +154 -0
  140. data/generators/ccls_engine/templates/javascripts/jrails.js +1 -0
  141. data/generators/ccls_engine/templates/migrations/create_user_invitations.rb +18 -0
  142. data/generators/ccls_engine/templates/migrations/create_users.rb +33 -0
  143. data/generators/ccls_engine/templates/migrations/drop_user_invitations.rb +18 -0
  144. data/generators/ccls_engine/templates/stylesheets/ccls_engine.css +180 -0
  145. data/generators/ccls_engine/templates/stylesheets/user.css +35 -0
  146. data/generators/ccls_engine/templates/stylesheets/users.css +23 -0
  147. data/generators/ccls_engine/templates/unit/core_extension_test.rb +18 -0
  148. data/generators/ccls_engine/templates/unit/role_test.rb +30 -0
  149. data/generators/ccls_engine/templates/unit/user_test.rb +321 -0
  150. data/lib/ccls-ccls_engine.rb +1 -0
  151. data/lib/ccls_engine.rb +135 -0
  152. data/lib/ccls_engine/action_view_extension.rb +3 -0
  153. data/lib/ccls_engine/action_view_extension/base.rb +53 -0
  154. data/lib/ccls_engine/action_view_extension/form_builder.rb +39 -0
  155. data/lib/ccls_engine/active_record_extension.rb +2 -0
  156. data/lib/ccls_engine/active_record_extension/base.rb +70 -0
  157. data/lib/ccls_engine/active_record_shared.rb +8 -0
  158. data/lib/ccls_engine/assertions.rb +69 -0
  159. data/lib/ccls_engine/autotest.rb +54 -0
  160. data/lib/ccls_engine/ccls_user.rb +117 -0
  161. data/lib/ccls_engine/core_extension.rb +14 -0
  162. data/lib/ccls_engine/date_and_time_formats.rb +30 -0
  163. data/lib/ccls_engine/factories.rb +880 -0
  164. data/lib/ccls_engine/factory_test_helper.rb +276 -0
  165. data/lib/ccls_engine/helper.rb +112 -0
  166. data/lib/ccls_engine/icf_master_tracker_update_test_helper.rb +121 -0
  167. data/lib/ccls_engine/live_birth_data_update_test_helper.rb +110 -0
  168. data/lib/ccls_engine/package_test_helper.rb +49 -0
  169. data/lib/ccls_engine/shared_database.rb +20 -0
  170. data/lib/ccls_engine/tasks.rb +1 -0
  171. data/lib/ccls_engine/test_tasks.rb +52 -0
  172. data/lib/ccls_engine/translation_table.rb +86 -0
  173. data/lib/shared_migration.rb +5 -0
  174. data/lib/surveyor/survey_extensions.rb +125 -0
  175. data/lib/tasks/application.rake +286 -0
  176. data/lib/tasks/calnet_authenticated.rake +6 -0
  177. data/lib/tasks/common_lib.rake +7 -0
  178. data/lib/tasks/database.rake +288 -0
  179. data/lib/tasks/documentation.rake +71 -0
  180. data/lib/tasks/homex_import.rake +723 -0
  181. data/lib/tasks/odms_import.rake +1116 -0
  182. data/lib/tasks/simply_authorized.rake +6 -0
  183. data/lib/tasks/ucb_ccls_engine_tasks.rake +4 -0
  184. data/lib/tasks/use_db.rake +4 -0
  185. data/rails/init.rb +4 -0
  186. data/test/unit/ccls/abstract_search_test.rb +150 -0
  187. data/test/unit/ccls/abstract_test.rb +674 -0
  188. data/test/unit/ccls/address_test.rb +155 -0
  189. data/test/unit/ccls/address_type_test.rb +25 -0
  190. data/test/unit/ccls/addressing_test.rb +466 -0
  191. data/test/unit/ccls/aliquot_sample_format_test.rb +20 -0
  192. data/test/unit/ccls/aliquot_test.rb +156 -0
  193. data/test/unit/ccls/analysis_test.rb +31 -0
  194. data/test/unit/ccls/bc_request_test.rb +43 -0
  195. data/test/unit/ccls/candidate_control_test.rb +712 -0
  196. data/test/unit/ccls/context_data_source_test.rb +26 -0
  197. data/test/unit/ccls/context_test.rb +40 -0
  198. data/test/unit/ccls/core_extension_test.rb +17 -0
  199. data/test/unit/ccls/county_test.rb +34 -0
  200. data/test/unit/ccls/data_source_test.rb +41 -0
  201. data/test/unit/ccls/diagnosis_test.rb +51 -0
  202. data/test/unit/ccls/document_type_test.rb +35 -0
  203. data/test/unit/ccls/document_version_test.rb +68 -0
  204. data/test/unit/ccls/enrollment_test.rb +575 -0
  205. data/test/unit/ccls/follow_up_test.rb +23 -0
  206. data/test/unit/ccls/follow_up_type_test.rb +34 -0
  207. data/test/unit/ccls/gift_card_search_test.rb +153 -0
  208. data/test/unit/ccls/gift_card_test.rb +40 -0
  209. data/test/unit/ccls/home_exposure_response_test.rb +83 -0
  210. data/test/unit/ccls/homex_outcome_test.rb +199 -0
  211. data/test/unit/ccls/hospital_test.rb +102 -0
  212. data/test/unit/ccls/icf_master_id_test.rb +30 -0
  213. data/test/unit/ccls/icf_master_tracker_change_test.rb +14 -0
  214. data/test/unit/ccls/icf_master_tracker_test.rb +132 -0
  215. data/test/unit/ccls/icf_master_tracker_update_test.rb +176 -0
  216. data/test/unit/ccls/ineligible_reason_test.rb +48 -0
  217. data/test/unit/ccls/instrument_test.rb +62 -0
  218. data/test/unit/ccls/instrument_type_test.rb +39 -0
  219. data/test/unit/ccls/instrument_version_test.rb +71 -0
  220. data/test/unit/ccls/interview_method_test.rb +44 -0
  221. data/test/unit/ccls/interview_outcome_test.rb +34 -0
  222. data/test/unit/ccls/interview_test.rb +298 -0
  223. data/test/unit/ccls/language_test.rb +47 -0
  224. data/test/unit/ccls/live_birth_data_update_test.rb +358 -0
  225. data/test/unit/ccls/operational_event_test.rb +187 -0
  226. data/test/unit/ccls/operational_event_type_test.rb +51 -0
  227. data/test/unit/ccls/organization_test.rb +64 -0
  228. data/test/unit/ccls/patient_test.rb +538 -0
  229. data/test/unit/ccls/person_test.rb +55 -0
  230. data/test/unit/ccls/phone_number_test.rb +244 -0
  231. data/test/unit/ccls/phone_type_test.rb +32 -0
  232. data/test/unit/ccls/project_outcome_test.rb +34 -0
  233. data/test/unit/ccls/project_test.rb +60 -0
  234. data/test/unit/ccls/race_test.rb +37 -0
  235. data/test/unit/ccls/refusal_reason_test.rb +52 -0
  236. data/test/unit/ccls/role_test.rb +26 -0
  237. data/test/unit/ccls/sample_kit_test.rb +35 -0
  238. data/test/unit/ccls/sample_outcome_test.rb +34 -0
  239. data/test/unit/ccls/sample_temperature_test.rb +25 -0
  240. data/test/unit/ccls/sample_test.rb +363 -0
  241. data/test/unit/ccls/sample_type_test.rb +58 -0
  242. data/test/unit/ccls/section_test.rb +34 -0
  243. data/test/unit/ccls/state_test.rb +31 -0
  244. data/test/unit/ccls/study_subject_abstracts_test.rb +115 -0
  245. data/test/unit/ccls/study_subject_addresses_test.rb +93 -0
  246. data/test/unit/ccls/study_subject_duplicates_test.rb +407 -0
  247. data/test/unit/ccls/study_subject_enrollments_test.rb +65 -0
  248. data/test/unit/ccls/study_subject_homex_outcome_test.rb +64 -0
  249. data/test/unit/ccls/study_subject_identifier_test.rb +439 -0
  250. data/test/unit/ccls/study_subject_interviews_test.rb +26 -0
  251. data/test/unit/ccls/study_subject_languages_test.rb +142 -0
  252. data/test/unit/ccls/study_subject_operational_events_test.rb +53 -0
  253. data/test/unit/ccls/study_subject_patient_test.rb +249 -0
  254. data/test/unit/ccls/study_subject_pii_test.rb +278 -0
  255. data/test/unit/ccls/study_subject_races_test.rb +203 -0
  256. data/test/unit/ccls/study_subject_search_test.rb +704 -0
  257. data/test/unit/ccls/study_subject_test.rb +770 -0
  258. data/test/unit/ccls/subject_language_test.rb +43 -0
  259. data/test/unit/ccls/subject_race_test.rb +35 -0
  260. data/test/unit/ccls/subject_relationship_test.rb +43 -0
  261. data/test/unit/ccls/subject_type_test.rb +40 -0
  262. data/test/unit/ccls/tracing_status_test.rb +32 -0
  263. data/test/unit/ccls/transfer_test.rb +81 -0
  264. data/test/unit/ccls/translation_table_test.rb +40 -0
  265. data/test/unit/ccls/unit_test.rb +21 -0
  266. data/test/unit/ccls/user_test.rb +156 -0
  267. data/test/unit/ccls/vital_status_test.rb +36 -0
  268. data/test/unit/ccls/zip_code_test.rb +55 -0
  269. metadata +633 -0
@@ -0,0 +1,31 @@
1
+ # == requires
2
+ # * code ( unique )
3
+ # * description ( unique and > 3 chars )
4
+ class Race < ActiveRecordShared
5
+
6
+ acts_as_list
7
+ default_scope :order => :position
8
+
9
+ acts_like_a_hash
10
+
11
+ validates_presence_of :code
12
+ validates_uniqueness_of :code
13
+ validates_length_of :code, :maximum => 250, :allow_blank => true
14
+
15
+ # Returns description
16
+ def to_s
17
+ description
18
+ end
19
+
20
+ # Returns description
21
+ def name
22
+ description
23
+ end
24
+
25
+ # Returns boolean of comparison
26
+ # true only if key == 'other'
27
+ def is_other?
28
+ key == 'other'
29
+ end
30
+
31
+ end
@@ -0,0 +1,23 @@
1
+ # == requires
2
+ # * description ( unique and > 3 chars )
3
+ class RefusalReason < ActiveRecordShared
4
+
5
+ acts_as_list
6
+ default_scope :order => :position
7
+
8
+ acts_like_a_hash
9
+
10
+ has_many :enrollments
11
+
12
+ # Returns description
13
+ def to_s
14
+ description
15
+ end
16
+
17
+ # Returns boolean of comparison
18
+ # true only if key == 'other'
19
+ def is_other?
20
+ key == 'other'
21
+ end
22
+
23
+ end
@@ -0,0 +1,168 @@
1
+ # == requires
2
+ # * enrollment_id
3
+ # * unit_id
4
+ class Sample < ActiveRecordShared
5
+
6
+ belongs_to :aliquot_sample_format
7
+ belongs_to :sample_type
8
+ belongs_to :organization, :foreign_key => 'location_id'
9
+ belongs_to :unit
10
+ has_many :aliquots
11
+ belongs_to :project
12
+ belongs_to :study_subject
13
+ belongs_to :sample_temperature
14
+
15
+ attr_protected :study_subject_id, :study_subject
16
+
17
+ has_one :sample_kit
18
+ accepts_nested_attributes_for :sample_kit
19
+
20
+ named_scope :pending, :conditions => {
21
+ :received_by_ccls_at => nil }
22
+
23
+ named_scope :collected, :conditions => [
24
+ 'received_by_ccls_at IS NOT NULL' ]
25
+
26
+ validates_presence_of :sample_type_id
27
+ validates_presence_of :sample_type, :if => :sample_type_id
28
+ validates_presence_of :study_subject_id
29
+ validates_presence_of :study_subject, :if => :study_subject_id
30
+ validates_presence_of :project_id
31
+ validates_presence_of :project, :if => :project_id
32
+
33
+ validates_presence_of :sent_to_subject_on, :if => :collected_at
34
+ validates_presence_of :collected_at, :if => :received_by_ccls_at
35
+ validates_presence_of :location_id, :if => :sent_to_lab_on
36
+ validates_presence_of :received_by_ccls_at, :if => :sent_to_lab_on
37
+ validates_presence_of :sent_to_lab_on, :if => :received_by_lab_on
38
+ validates_presence_of :received_by_lab_on, :if => :aliquotted_on
39
+
40
+ # NOTE I'm not sure how this validation will work for datetimes.
41
+ validates_complete_date_for :sent_to_subject_on, :allow_nil => true
42
+ # validates_complete_date_for :collected_at, :allow_nil => true
43
+ # validates_complete_date_for :received_by_ccls_at, :allow_nil => true
44
+ validates_complete_date_for :sent_to_lab_on, :allow_nil => true
45
+ validates_complete_date_for :received_by_lab_on, :allow_nil => true
46
+ validates_complete_date_for :aliquotted_on, :allow_nil => true
47
+ validates_complete_date_for :receipt_confirmed_on, :allow_nil => true
48
+
49
+ validates_past_date_for :sent_to_subject_on
50
+ validates_past_date_for :collected_at
51
+ validates_past_date_for :received_by_ccls_at
52
+ validates_past_date_for :sent_to_lab_on
53
+ validates_past_date_for :received_by_lab_on
54
+ validates_past_date_for :aliquotted_on
55
+ validates_past_date_for :receipt_confirmed_on
56
+
57
+ validate :date_chronology
58
+
59
+ # Returns the parent of this sample type
60
+ def sample_type_parent
61
+ sample_type.parent
62
+ end
63
+
64
+ before_save :update_sample_outcome
65
+
66
+ protected
67
+
68
+ def date_chronology
69
+ errors.add(:collected_at, "must be after sent_to_subject_on"
70
+ ) if collected_at_is_before_sent_to_subject_on?
71
+ errors.add(:received_by_ccls_at, "must be after collected_at"
72
+ ) if received_by_ccls_at_is_before_collected_at?
73
+ errors.add(:sent_to_lab_on, "must be after received_by_ccls_at"
74
+ ) if sent_to_lab_on_is_before_received_by_ccls_at?
75
+ errors.add(:received_by_lab_on, "must be after sent_to_lab_on"
76
+ ) if received_by_lab_on_is_before_sent_to_lab_on?
77
+ errors.add(:aliquotted_on, "must be after received_by_lab_on"
78
+ ) if aliquotted_on_is_before_received_by_lab_on?
79
+ end
80
+
81
+ #ArgumentError: comparison of Date with ActiveSupport::TimeWithZone failed
82
+ # app/models/sample.rb:77:in `>'
83
+ # app/models/sample.rb:77:in `collected_at_is_before_sent_to_subject_on?'
84
+ def collected_at_is_before_sent_to_subject_on?
85
+ (( sent_to_subject_on && collected_at ) &&
86
+ ( sent_to_subject_on > collected_at.to_date ))
87
+ # ( sent_to_subject_on > collected_at ))
88
+ end
89
+
90
+ def received_by_ccls_at_is_before_collected_at?
91
+ (( collected_at && received_by_ccls_at ) &&
92
+ ( collected_at > received_by_ccls_at ))
93
+ end
94
+
95
+ def sent_to_lab_on_is_before_received_by_ccls_at?
96
+ (( received_by_ccls_at && sent_to_lab_on ) &&
97
+ ( received_by_ccls_at > sent_to_lab_on ))
98
+ end
99
+
100
+ def received_by_lab_on_is_before_sent_to_lab_on?
101
+ (( sent_to_lab_on && received_by_lab_on ) &&
102
+ ( sent_to_lab_on > received_by_lab_on ))
103
+ end
104
+
105
+ def aliquotted_on_is_before_received_by_lab_on?
106
+ (( received_by_lab_on && aliquotted_on ) &&
107
+ ( received_by_lab_on > aliquotted_on ))
108
+ end
109
+
110
+ def update_sample_outcome
111
+
112
+
113
+ if study_subject.enrollments.find_by_project_id(Project['HomeExposures'].id)
114
+ # if enrollment.project_id == Project['HomeExposures'].id
115
+ # study_subject = enrollment.study_subject
116
+
117
+
118
+ ho = study_subject.homex_outcome || study_subject.create_homex_outcome
119
+ so,date = if sent_to_lab_on_changed? && !sent_to_lab_on.nil?
120
+ [SampleOutcome['lab'], sent_to_lab_on ]
121
+ elsif received_by_ccls_at_changed? && !received_by_ccls_at.nil?
122
+ [SampleOutcome['received'], received_by_ccls_at ]
123
+ elsif sent_to_subject_on_changed? && !sent_to_subject_on.nil?
124
+ [SampleOutcome['sent'], sent_to_subject_on ]
125
+ end
126
+ ho.update_attributes({
127
+ :sample_outcome => so,
128
+ :sample_outcome_on => date }) if so
129
+ end
130
+ end
131
+
132
+ end
133
+ __END__
134
+
135
+
136
+ It appears that the "newer" classes know how to compare with the "older" ones, but not vice versa, which makes sense.
137
+
138
+ My comparisons in Sample should just have the "newer" class, the *_at field, first and compare it to the "older" *_on field. OR convert the DateTime to a date. Comparison of a Date to a DateTime will be confusing as it doesn't just compare the date, it takes the time zone into account which isn't 100% obvious. I think that it converts it to UTC before comparing. This could effectively make the comparison incorrect.
139
+
140
+ YES. Add a "to_date" to the _at fields.
141
+
142
+
143
+ >> Time.now
144
+ => Tue Mar 06 20:00:06 -0800 2012
145
+ >> Time.now.class
146
+ => Time
147
+
148
+ >> Time.zone.now
149
+ => Wed, 07 Mar 2012 03:54:31 UTC +00:00
150
+ >> Time.zone.now.class
151
+ => ActiveSupport::TimeWithZone
152
+
153
+ >> Time.zone.now > Date.today
154
+ => true
155
+
156
+ >> Date.today < Time.zone.now
157
+ ArgumentError: comparison of Date with ActiveSupport::TimeWithZone failed
158
+ from (irb):49:in `<'
159
+ from (irb):49
160
+
161
+ >> Date.today < Time.now
162
+ ArgumentError: comparison of Date with Time failed
163
+ from (irb):50:in `<'
164
+ from (irb):50
165
+
166
+
167
+ Also, even if the *_at field is given a Date value, it will be typecast to ActiveSupport::TimeWithZone so there is no terrible need to update all of the tests.
168
+
@@ -0,0 +1,14 @@
1
+ # A kit is 2 packages used for retrieving samples.
2
+ class SampleKit < ActiveRecordShared
3
+
4
+ # add tracking numbers to kit?
5
+ # used to be in packages
6
+ # 20120213 - Removing FedEx API, Packages and Tracks.
7
+
8
+ belongs_to :sample
9
+
10
+ delegate :study_subject, :to => :sample
11
+
12
+ validates_uniqueness_of :sample_id, :allow_nil => true
13
+
14
+ end
@@ -0,0 +1,16 @@
1
+ # don't know exactly
2
+ class SampleOutcome < ActiveRecordShared
3
+
4
+ acts_as_list
5
+ default_scope :order => :position
6
+
7
+ acts_like_a_hash
8
+
9
+ has_many :homex_outcomes
10
+
11
+ # Returns description
12
+ def to_s
13
+ description
14
+ end
15
+
16
+ end
@@ -0,0 +1,14 @@
1
+ class SampleTemperature < ActiveRecordShared
2
+
3
+ acts_as_list
4
+ default_scope :order => :position
5
+
6
+ acts_like_a_hash
7
+
8
+ has_many :samples
9
+
10
+ def to_s
11
+ description
12
+ end
13
+
14
+ end
@@ -0,0 +1,37 @@
1
+ # == requires
2
+ # * description ( unique and > 3 chars )
3
+ class SampleType < ActiveRecordShared
4
+
5
+ acts_as_list :scope => :parent_id
6
+ # default_scope :order => :position
7
+ default_scope :order => 'parent_id, position, description ASC'
8
+
9
+ acts_like_a_hash
10
+
11
+ has_many :samples
12
+
13
+ belongs_to :parent, :class_name => 'SampleType'
14
+ has_many :children,
15
+ :class_name => 'SampleType',
16
+ :foreign_key => 'parent_id',
17
+ :dependent => :nullify
18
+
19
+ named_scope :roots, :conditions => { :parent_id => nil }
20
+
21
+ named_scope :not_roots, :conditions => [
22
+ 'sample_types.parent_id IS NOT NULL' ]
23
+
24
+ # Returns description
25
+ def to_s
26
+ description
27
+ end
28
+
29
+ def is_root?
30
+ parent_id.blank?
31
+ end
32
+
33
+ def is_child?
34
+ !is_root?
35
+ end
36
+
37
+ end
@@ -0,0 +1,195 @@
1
+ #
2
+ # Originally from http://railscasts.com/episodes/111-advanced-search-form
3
+ # however, I have modified it heavily and made it quite abstract.
4
+ # Its still a bit muddy, but I'd like to replace it with rsolr.
5
+ #
6
+ class Search
7
+
8
+ class << self
9
+ def valid_orders
10
+ @valid_orders
11
+ end
12
+ def valid_orders=(more_orders)
13
+ @valid_orders = more_orders
14
+ end
15
+ def searchable_attributes
16
+ @searchable_attributes
17
+ end
18
+ def searchable_attributes=(more_attributes)
19
+ @searchable_attributes = more_attributes
20
+ end
21
+ def attr_accessors
22
+ @attr_accessors
23
+ end
24
+ def attr_accessors=(more_accessors) # extend with += [ :something ] NOT << :something
25
+ @attr_accessors = more_accessors
26
+ attr_accessor *@attr_accessors
27
+ end
28
+ end
29
+ self.valid_orders = HashWithIndifferentAccess.new
30
+ self.searchable_attributes = []
31
+ self.attr_accessors = [ :order, :dir, :includes, :paginate, :per_page, :page ]
32
+
33
+ def valid_orders
34
+ self.class.valid_orders
35
+ end
36
+
37
+ def searchable_attributes
38
+ self.class.searchable_attributes
39
+ end
40
+
41
+ def attr_accessors
42
+ self.class.attr_accessors
43
+ end
44
+
45
+ def search_order
46
+ if valid_orders.has_key?(@order)
47
+ order_string = if valid_orders[@order].blank?
48
+ @order
49
+ else
50
+ valid_orders[@order]
51
+ end
52
+ dir = case @dir.try(:downcase)
53
+ when 'desc' then 'desc'
54
+ else 'asc'
55
+ end
56
+ [order_string,dir].join(' ')
57
+ else
58
+ nil
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def paginate?
65
+ (@paginate.nil?) ? true : @paginate
66
+ end
67
+
68
+ def initialize(options={})
69
+ self.class.send('attr_accessor', *searchable_attributes)
70
+ options.each do |attr,value|
71
+ if attr_accessors.include?(attr.to_sym) ||
72
+ searchable_attributes.include?(attr.to_sym)
73
+ self.send("#{attr}=",value)
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.inherited(subclass)
79
+ # USE DUP! Without it, the two will share the same object_id
80
+ # resulting is cross contamination
81
+ subclass.searchable_attributes = searchable_attributes.dup
82
+ subclass.attr_accessors = attr_accessors.dup
83
+ subclass.valid_orders = valid_orders.dup
84
+ # Create 'shortcut'
85
+ # StudySubjectSearch(options) -> StudySubjectSearch.new(options)
86
+ Object.class_eval do
87
+ define_method subclass.to_s do |*args|
88
+ subclass.send(:new,*args)
89
+ end
90
+ end
91
+ end
92
+
93
+ # This may work for the simple stuff, but I suspect
94
+ # that once things get complicated, it will unravel.
95
+
96
+ def conditions
97
+ [conditions_clauses.join(' AND '), *conditions_options]
98
+ end
99
+
100
+ def conditions_clauses
101
+ conditions_parts.map { |condition| condition.first }
102
+ end
103
+
104
+ def conditions_options
105
+ # conditions_parts.map { |condition| condition[1..-1] }.flatten
106
+ #
107
+ # the above flatten breaks the "IN (?)" style search
108
+ #
109
+ # conditions_parts.map { |condition| condition[1..-1] }
110
+ # This fixes it, but is kinda bulky
111
+ # opts = []
112
+ # conditions_parts.each do |condition|
113
+ # condition[1..-1].each{|cp| opts << cp}
114
+ # end
115
+ # opts
116
+ # That's better!
117
+ parts = conditions_parts.map { |condition| condition[1..-1] }.flatten(1)
118
+
119
+ # The "parts" contain the variables inserted in the query.
120
+ # Apparently, we can't mix the ? style with the :var_name style,
121
+ # but we can only have 1 trailing hash so we need to merge all
122
+ # of the trailing hashes.
123
+
124
+ # symbol_options = HashWithIndifferentAccess.new
125
+ # while( !( h = parts.extract_options! ).empty? ) do
126
+ # symbol_options.merge!(h)
127
+ # end
128
+
129
+ # parts.push(symbol_options)
130
+
131
+ # caller is expecting an array
132
+ [parts.inject(:merge)]
133
+ end
134
+
135
+ def conditions_parts
136
+ private_methods(false).grep(/_conditions$/).map { |m| send(m) }.compact
137
+ end
138
+
139
+ # Join order can be important if joining on other joins
140
+ # so added a sort. Added a "a_" to those joins which must go first.
141
+ # Crude solution, but a solution nonetheless.
142
+ def joins
143
+ private_methods(false).grep(/_joins$/).sort.map { |m| send(m) }.compact
144
+ end
145
+
146
+ def select
147
+ # :select - By default, this is "*" as in "SELECT * FROM",
148
+ # but can be changed if you, for example, want to do a join
149
+ # but not include the joined columns. Takes a string with the
150
+ # SELECT SQL fragment (e.g. "id, name").
151
+ selects = private_methods(false).grep(/_selects$/).sort.map { |m| send(m) }.compact
152
+ # select CANNOT be ''
153
+ # ActiveRecord::StatementInvalid: Mysql::Error: You have an error in your SQL syntax;
154
+ # check the manual that corresponds to your MySQL server version for the right
155
+ # syntax to use near 'FROM `study_subjects` LIMIT 0, 25' at line 1:
156
+ # SELECT FROM `study_subjects` LIMIT 0, 25
157
+ # nil will cause default use of '*', which could also be passed
158
+ ( selects.empty? ) ? nil : selects.join(',')
159
+ end
160
+
161
+ def group
162
+ # :group - An attribute name by which the result should be grouped.
163
+ # Uses the GROUP BY SQL-clause
164
+ groups = private_methods(false).grep(/_groups$/).sort.map { |m| send(m) }.compact
165
+ # ActiveRecord::StatementInvalid: Mysql::Error: You have an error in your SQL syntax;
166
+ # check the manual that corresponds to your MySQL server version for the right
167
+ # syntax to use near '' at line 1: SELECT * FROM `study_subjects` GROUP BY
168
+ # nil will cause group by to not be used
169
+ ( groups.empty? ) ? nil : groups.join(',')
170
+ end
171
+
172
+ def having
173
+ # :having - Combined with :group this can be used to filter the records
174
+ # that a GROUP BY returns. Uses the HAVING SQL-clause.
175
+ # this is very similar to :conditions/WHERE so may have to add all of the
176
+ # conditions_* methods to handle
177
+ [having_clauses.join(' AND '), *having_options]
178
+ end
179
+
180
+ def having_clauses
181
+ having_parts.map { |condition| condition.first }
182
+ end
183
+
184
+ def having_options
185
+ parts = having_parts.map { |condition| condition[1..-1] }.flatten(1)
186
+ # just like conditions, these parts need to be hashes of symbol names
187
+ # for use in the sql command. Not ?.
188
+ [parts.inject(:merge)]
189
+ end
190
+
191
+ def having_parts
192
+ private_methods(false).grep(/_havings$/).map { |m| send(m) }.compact
193
+ end
194
+
195
+ end