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.
- data/README.rdoc +182 -0
- data/app/models/abstract.rb +181 -0
- data/app/models/abstract_search.rb +50 -0
- data/app/models/abstract_validations.rb +324 -0
- data/app/models/address.rb +70 -0
- data/app/models/address_type.rb +15 -0
- data/app/models/addressing.rb +147 -0
- data/app/models/aliquot.rb +44 -0
- data/app/models/aliquot_sample_format.rb +13 -0
- data/app/models/analysis.rb +14 -0
- data/app/models/bc_request.rb +20 -0
- data/app/models/candidate_control.rb +101 -0
- data/app/models/context.rb +23 -0
- data/app/models/context_data_source.rb +4 -0
- data/app/models/county.rb +16 -0
- data/app/models/data_source.rb +24 -0
- data/app/models/diagnosis.rb +23 -0
- data/app/models/document_type.rb +16 -0
- data/app/models/document_version.rb +27 -0
- data/app/models/enrollment.rb +78 -0
- data/app/models/enrollment_validations.rb +167 -0
- data/app/models/follow_up.rb +16 -0
- data/app/models/follow_up_type.rb +18 -0
- data/app/models/gift_card.rb +22 -0
- data/app/models/gift_card_search.rb +137 -0
- data/app/models/home_exposure_response.rb +24 -0
- data/app/models/homex_outcome.rb +75 -0
- data/app/models/hospital.rb +22 -0
- data/app/models/icf_master_id.rb +30 -0
- data/app/models/icf_master_tracker.rb +217 -0
- data/app/models/icf_master_tracker_change.rb +9 -0
- data/app/models/icf_master_tracker_update.rb +50 -0
- data/app/models/ineligible_reason.rb +26 -0
- data/app/models/instrument.rb +26 -0
- data/app/models/instrument_type.rb +17 -0
- data/app/models/instrument_version.rb +28 -0
- data/app/models/interview.rb +122 -0
- data/app/models/interview_method.rb +17 -0
- data/app/models/interview_outcome.rb +16 -0
- data/app/models/language.rb +28 -0
- data/app/models/live_birth_data_update.rb +142 -0
- data/app/models/operational_event.rb +99 -0
- data/app/models/operational_event_type.rb +31 -0
- data/app/models/organization.rb +28 -0
- data/app/models/patient.rb +63 -0
- data/app/models/patient_validations.rb +118 -0
- data/app/models/person.rb +28 -0
- data/app/models/phone_number.rb +105 -0
- data/app/models/phone_type.rb +15 -0
- data/app/models/project.rb +39 -0
- data/app/models/project_outcome.rb +19 -0
- data/app/models/race.rb +31 -0
- data/app/models/refusal_reason.rb +23 -0
- data/app/models/sample.rb +168 -0
- data/app/models/sample_kit.rb +14 -0
- data/app/models/sample_outcome.rb +16 -0
- data/app/models/sample_temperature.rb +14 -0
- data/app/models/sample_type.rb +37 -0
- data/app/models/search.rb +195 -0
- data/app/models/section.rb +18 -0
- data/app/models/state.rb +25 -0
- data/app/models/study_subject.rb +237 -0
- data/app/models/study_subject_abstracts.rb +47 -0
- data/app/models/study_subject_addresses.rb +34 -0
- data/app/models/study_subject_associations.rb +38 -0
- data/app/models/study_subject_duplicates.rb +111 -0
- data/app/models/study_subject_enrollments.rb +17 -0
- data/app/models/study_subject_homex_outcome.rb +22 -0
- data/app/models/study_subject_identifier.rb +153 -0
- data/app/models/study_subject_interviews.rb +25 -0
- data/app/models/study_subject_languages.rb +21 -0
- data/app/models/study_subject_operational_events.rb +66 -0
- data/app/models/study_subject_patient.rb +177 -0
- data/app/models/study_subject_pii.rb +74 -0
- data/app/models/study_subject_races.rb +25 -0
- data/app/models/study_subject_search.rb +260 -0
- data/app/models/study_subject_validations.rb +116 -0
- data/app/models/subject_language.rb +11 -0
- data/app/models/subject_race.rb +11 -0
- data/app/models/subject_relationship.rb +21 -0
- data/app/models/subject_type.rb +22 -0
- data/app/models/tracing_status.rb +20 -0
- data/app/models/transfer.rb +40 -0
- data/app/models/unit.rb +14 -0
- data/app/models/vital_status.rb +19 -0
- data/app/models/zip_code.rb +36 -0
- data/config/abstract_fields.yml +1038 -0
- data/config/abstract_sections.yml +77 -0
- data/config/home_exposure_response_fields.yml +583 -0
- data/config/icf_master_tracker_update.yml +56 -0
- data/config/live_birth_data_update.yml +56 -0
- data/config/shared_use_db.yml +4 -0
- data/generators/ccls_engine/USAGE +2 -0
- data/generators/ccls_engine/ccls_engine_generator.rb +123 -0
- data/generators/ccls_engine/templates/autotest_ccls_engine.rb +3 -0
- data/generators/ccls_engine/templates/ccls_engine.rake +12 -0
- data/generators/ccls_engine/templates/fixtures/address_types.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/context_data_sources.yml +54 -0
- data/generators/ccls_engine/templates/fixtures/contexts.yml +19 -0
- data/generators/ccls_engine/templates/fixtures/data_sources.yml +40 -0
- data/generators/ccls_engine/templates/fixtures/diagnoses.yml +40 -0
- data/generators/ccls_engine/templates/fixtures/document_types.yml +65 -0
- data/generators/ccls_engine/templates/fixtures/document_versions.csv +155 -0
- data/generators/ccls_engine/templates/fixtures/follow_up_types.yml +16 -0
- data/generators/ccls_engine/templates/fixtures/hospitals.yml +114 -0
- data/generators/ccls_engine/templates/fixtures/ineligible_reasons.yml +35 -0
- data/generators/ccls_engine/templates/fixtures/instrument_types.yml +26 -0
- data/generators/ccls_engine/templates/fixtures/instrument_versions.yml +22 -0
- data/generators/ccls_engine/templates/fixtures/instruments.yml +22 -0
- data/generators/ccls_engine/templates/fixtures/interview_methods.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/interview_outcomes.yml +31 -0
- data/generators/ccls_engine/templates/fixtures/languages.yml +34 -0
- data/generators/ccls_engine/templates/fixtures/operational_event_types.yml +141 -0
- data/generators/ccls_engine/templates/fixtures/organizations.yml +198 -0
- data/generators/ccls_engine/templates/fixtures/people.yml +130 -0
- data/generators/ccls_engine/templates/fixtures/phone_types.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/project_outcomes.yml +25 -0
- data/generators/ccls_engine/templates/fixtures/projects.yml +59 -0
- data/generators/ccls_engine/templates/fixtures/races.yml +52 -0
- data/generators/ccls_engine/templates/fixtures/refusal_reasons.yml +55 -0
- data/generators/ccls_engine/templates/fixtures/sample_outcomes.yml +36 -0
- data/generators/ccls_engine/templates/fixtures/sample_temperatures.yml +16 -0
- data/generators/ccls_engine/templates/fixtures/sample_types.yml +147 -0
- data/generators/ccls_engine/templates/fixtures/sections.yml +31 -0
- data/generators/ccls_engine/templates/fixtures/states.yml +363 -0
- data/generators/ccls_engine/templates/fixtures/subject_relationships.yml +46 -0
- data/generators/ccls_engine/templates/fixtures/subject_types.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/tracing_statuses.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/units.yml +13 -0
- data/generators/ccls_engine/templates/fixtures/vital_statuses.yml +28 -0
- data/generators/ccls_engine/templates/functional/roles_controller_test.rb +142 -0
- data/generators/ccls_engine/templates/functional/sessions_controller_test.rb +19 -0
- data/generators/ccls_engine/templates/functional/users_controller_test.rb +94 -0
- data/generators/ccls_engine/templates/images/sort_down.png +0 -0
- data/generators/ccls_engine/templates/images/sort_up.png +0 -0
- data/generators/ccls_engine/templates/initializer.rb +28 -0
- data/generators/ccls_engine/templates/javascripts/ccls_engine.js +24 -0
- data/generators/ccls_engine/templates/javascripts/jquery-ui.js +763 -0
- data/generators/ccls_engine/templates/javascripts/jquery.js +154 -0
- data/generators/ccls_engine/templates/javascripts/jrails.js +1 -0
- data/generators/ccls_engine/templates/migrations/create_user_invitations.rb +18 -0
- data/generators/ccls_engine/templates/migrations/create_users.rb +33 -0
- data/generators/ccls_engine/templates/migrations/drop_user_invitations.rb +18 -0
- data/generators/ccls_engine/templates/stylesheets/ccls_engine.css +180 -0
- data/generators/ccls_engine/templates/stylesheets/user.css +35 -0
- data/generators/ccls_engine/templates/stylesheets/users.css +23 -0
- data/generators/ccls_engine/templates/unit/core_extension_test.rb +18 -0
- data/generators/ccls_engine/templates/unit/role_test.rb +30 -0
- data/generators/ccls_engine/templates/unit/user_test.rb +321 -0
- data/lib/ccls-ccls_engine.rb +1 -0
- data/lib/ccls_engine.rb +135 -0
- data/lib/ccls_engine/action_view_extension.rb +3 -0
- data/lib/ccls_engine/action_view_extension/base.rb +53 -0
- data/lib/ccls_engine/action_view_extension/form_builder.rb +39 -0
- data/lib/ccls_engine/active_record_extension.rb +2 -0
- data/lib/ccls_engine/active_record_extension/base.rb +70 -0
- data/lib/ccls_engine/active_record_shared.rb +8 -0
- data/lib/ccls_engine/assertions.rb +69 -0
- data/lib/ccls_engine/autotest.rb +54 -0
- data/lib/ccls_engine/ccls_user.rb +117 -0
- data/lib/ccls_engine/core_extension.rb +14 -0
- data/lib/ccls_engine/date_and_time_formats.rb +30 -0
- data/lib/ccls_engine/factories.rb +880 -0
- data/lib/ccls_engine/factory_test_helper.rb +276 -0
- data/lib/ccls_engine/helper.rb +112 -0
- data/lib/ccls_engine/icf_master_tracker_update_test_helper.rb +121 -0
- data/lib/ccls_engine/live_birth_data_update_test_helper.rb +110 -0
- data/lib/ccls_engine/package_test_helper.rb +49 -0
- data/lib/ccls_engine/shared_database.rb +20 -0
- data/lib/ccls_engine/tasks.rb +1 -0
- data/lib/ccls_engine/test_tasks.rb +52 -0
- data/lib/ccls_engine/translation_table.rb +86 -0
- data/lib/shared_migration.rb +5 -0
- data/lib/surveyor/survey_extensions.rb +125 -0
- data/lib/tasks/application.rake +286 -0
- data/lib/tasks/calnet_authenticated.rake +6 -0
- data/lib/tasks/common_lib.rake +7 -0
- data/lib/tasks/database.rake +288 -0
- data/lib/tasks/documentation.rake +71 -0
- data/lib/tasks/homex_import.rake +723 -0
- data/lib/tasks/odms_import.rake +1116 -0
- data/lib/tasks/simply_authorized.rake +6 -0
- data/lib/tasks/ucb_ccls_engine_tasks.rake +4 -0
- data/lib/tasks/use_db.rake +4 -0
- data/rails/init.rb +4 -0
- data/test/unit/ccls/abstract_search_test.rb +150 -0
- data/test/unit/ccls/abstract_test.rb +674 -0
- data/test/unit/ccls/address_test.rb +155 -0
- data/test/unit/ccls/address_type_test.rb +25 -0
- data/test/unit/ccls/addressing_test.rb +466 -0
- data/test/unit/ccls/aliquot_sample_format_test.rb +20 -0
- data/test/unit/ccls/aliquot_test.rb +156 -0
- data/test/unit/ccls/analysis_test.rb +31 -0
- data/test/unit/ccls/bc_request_test.rb +43 -0
- data/test/unit/ccls/candidate_control_test.rb +712 -0
- data/test/unit/ccls/context_data_source_test.rb +26 -0
- data/test/unit/ccls/context_test.rb +40 -0
- data/test/unit/ccls/core_extension_test.rb +17 -0
- data/test/unit/ccls/county_test.rb +34 -0
- data/test/unit/ccls/data_source_test.rb +41 -0
- data/test/unit/ccls/diagnosis_test.rb +51 -0
- data/test/unit/ccls/document_type_test.rb +35 -0
- data/test/unit/ccls/document_version_test.rb +68 -0
- data/test/unit/ccls/enrollment_test.rb +575 -0
- data/test/unit/ccls/follow_up_test.rb +23 -0
- data/test/unit/ccls/follow_up_type_test.rb +34 -0
- data/test/unit/ccls/gift_card_search_test.rb +153 -0
- data/test/unit/ccls/gift_card_test.rb +40 -0
- data/test/unit/ccls/home_exposure_response_test.rb +83 -0
- data/test/unit/ccls/homex_outcome_test.rb +199 -0
- data/test/unit/ccls/hospital_test.rb +102 -0
- data/test/unit/ccls/icf_master_id_test.rb +30 -0
- data/test/unit/ccls/icf_master_tracker_change_test.rb +14 -0
- data/test/unit/ccls/icf_master_tracker_test.rb +132 -0
- data/test/unit/ccls/icf_master_tracker_update_test.rb +176 -0
- data/test/unit/ccls/ineligible_reason_test.rb +48 -0
- data/test/unit/ccls/instrument_test.rb +62 -0
- data/test/unit/ccls/instrument_type_test.rb +39 -0
- data/test/unit/ccls/instrument_version_test.rb +71 -0
- data/test/unit/ccls/interview_method_test.rb +44 -0
- data/test/unit/ccls/interview_outcome_test.rb +34 -0
- data/test/unit/ccls/interview_test.rb +298 -0
- data/test/unit/ccls/language_test.rb +47 -0
- data/test/unit/ccls/live_birth_data_update_test.rb +358 -0
- data/test/unit/ccls/operational_event_test.rb +187 -0
- data/test/unit/ccls/operational_event_type_test.rb +51 -0
- data/test/unit/ccls/organization_test.rb +64 -0
- data/test/unit/ccls/patient_test.rb +538 -0
- data/test/unit/ccls/person_test.rb +55 -0
- data/test/unit/ccls/phone_number_test.rb +244 -0
- data/test/unit/ccls/phone_type_test.rb +32 -0
- data/test/unit/ccls/project_outcome_test.rb +34 -0
- data/test/unit/ccls/project_test.rb +60 -0
- data/test/unit/ccls/race_test.rb +37 -0
- data/test/unit/ccls/refusal_reason_test.rb +52 -0
- data/test/unit/ccls/role_test.rb +26 -0
- data/test/unit/ccls/sample_kit_test.rb +35 -0
- data/test/unit/ccls/sample_outcome_test.rb +34 -0
- data/test/unit/ccls/sample_temperature_test.rb +25 -0
- data/test/unit/ccls/sample_test.rb +363 -0
- data/test/unit/ccls/sample_type_test.rb +58 -0
- data/test/unit/ccls/section_test.rb +34 -0
- data/test/unit/ccls/state_test.rb +31 -0
- data/test/unit/ccls/study_subject_abstracts_test.rb +115 -0
- data/test/unit/ccls/study_subject_addresses_test.rb +93 -0
- data/test/unit/ccls/study_subject_duplicates_test.rb +407 -0
- data/test/unit/ccls/study_subject_enrollments_test.rb +65 -0
- data/test/unit/ccls/study_subject_homex_outcome_test.rb +64 -0
- data/test/unit/ccls/study_subject_identifier_test.rb +439 -0
- data/test/unit/ccls/study_subject_interviews_test.rb +26 -0
- data/test/unit/ccls/study_subject_languages_test.rb +142 -0
- data/test/unit/ccls/study_subject_operational_events_test.rb +53 -0
- data/test/unit/ccls/study_subject_patient_test.rb +249 -0
- data/test/unit/ccls/study_subject_pii_test.rb +278 -0
- data/test/unit/ccls/study_subject_races_test.rb +203 -0
- data/test/unit/ccls/study_subject_search_test.rb +704 -0
- data/test/unit/ccls/study_subject_test.rb +770 -0
- data/test/unit/ccls/subject_language_test.rb +43 -0
- data/test/unit/ccls/subject_race_test.rb +35 -0
- data/test/unit/ccls/subject_relationship_test.rb +43 -0
- data/test/unit/ccls/subject_type_test.rb +40 -0
- data/test/unit/ccls/tracing_status_test.rb +32 -0
- data/test/unit/ccls/transfer_test.rb +81 -0
- data/test/unit/ccls/translation_table_test.rb +40 -0
- data/test/unit/ccls/unit_test.rb +21 -0
- data/test/unit/ccls/user_test.rb +156 -0
- data/test/unit/ccls/vital_status_test.rb +36 -0
- data/test/unit/ccls/zip_code_test.rb +55 -0
- metadata +633 -0
data/app/models/race.rb
ADDED
|
@@ -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,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
|