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
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Simply extracted some code to clean up model.
|
|
3
|
+
# I'd like to do this to all of the really big classes
|
|
4
|
+
# but let's see how this goes first.
|
|
5
|
+
#
|
|
6
|
+
module StudySubjectPii
|
|
7
|
+
def self.included(base)
|
|
8
|
+
# Must delay the calls to these ActiveRecord methods
|
|
9
|
+
# or it will raise many "undefined method"s.
|
|
10
|
+
base.class_eval do
|
|
11
|
+
|
|
12
|
+
# TODO include maiden_name just in case is mother???
|
|
13
|
+
def childs_names
|
|
14
|
+
[first_name, middle_name, last_name ]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns string containing study_subject's first, middle and last initials
|
|
18
|
+
def initials
|
|
19
|
+
childs_names.delete_if(&:blank?).collect{|s|s.chars.first}.join()
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns string containing study_subject's first, middle and last name
|
|
23
|
+
# Use delete_if(&:blank?) instead of compact, which only removes nils.
|
|
24
|
+
def full_name
|
|
25
|
+
fullname = childs_names.delete_if(&:blank?).join(' ')
|
|
26
|
+
( fullname.blank? ) ? '[name not available]' : fullname
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fathers_names
|
|
30
|
+
[father_first_name, father_middle_name, father_last_name ]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns string containing study_subject's father's first, middle and last name
|
|
34
|
+
def fathers_name
|
|
35
|
+
fathersname = fathers_names.delete_if(&:blank?).join(' ')
|
|
36
|
+
( fathersname.blank? ) ? '[name not available]' : fathersname
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def mothers_names
|
|
40
|
+
[mother_first_name, mother_middle_name, mother_last_name ]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns string containing study_subject's mother's first, middle and last name
|
|
44
|
+
# TODO what? no maiden name?
|
|
45
|
+
def mothers_name
|
|
46
|
+
mothersname = mothers_names.delete_if(&:blank?).join(' ')
|
|
47
|
+
( mothersname.blank? ) ? '[name not available]' : mothersname
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def guardians_names
|
|
51
|
+
[guardian_first_name, guardian_middle_name, guardian_last_name ]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Returns string containing study_subject's guardian's first, middle and last name
|
|
55
|
+
def guardians_name
|
|
56
|
+
guardiansname = guardians_names.delete_if(&:blank?).join(' ')
|
|
57
|
+
( guardiansname.blank? ) ? '[name not available]' : guardiansname
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# TODO I hate this. It is revolting. More? Yes, please.
|
|
62
|
+
#
|
|
63
|
+
# I don't know if I still need this
|
|
64
|
+
# commented out 20101014
|
|
65
|
+
# uncommented 20101014
|
|
66
|
+
def dob # overwrite default dob method for formatting
|
|
67
|
+
# added to_date to fix sqlite3 quirk which doesn't (why am I using sqlite3?) old comment?
|
|
68
|
+
# differentiate between times and dates.
|
|
69
|
+
read_attribute(:dob).try(:to_s,:dob).try(:to_date)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end # class_eval
|
|
73
|
+
end # included
|
|
74
|
+
end # StudySubjectPii
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Simply extracted some code to clean up model.
|
|
3
|
+
# I'd like to do this to all of the really big classes
|
|
4
|
+
# but let's see how this goes first.
|
|
5
|
+
#
|
|
6
|
+
module StudySubjectRaces
|
|
7
|
+
def self.included(base)
|
|
8
|
+
# Must delay the calls to these ActiveRecord methods
|
|
9
|
+
# or it will raise many "undefined method"s.
|
|
10
|
+
base.class_eval do
|
|
11
|
+
|
|
12
|
+
has_many :subject_races
|
|
13
|
+
has_many :races, :through => :subject_races
|
|
14
|
+
|
|
15
|
+
accepts_nested_attributes_for :subject_races,
|
|
16
|
+
:allow_destroy => true,
|
|
17
|
+
:reject_if => proc{|attributes| attributes['race_id'].blank? }
|
|
18
|
+
|
|
19
|
+
def race_names
|
|
20
|
+
races.collect(&:to_s).join(', ')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end # class_eval
|
|
24
|
+
end # included
|
|
25
|
+
end # StudySubjectRaces
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# This has gotton out of control. While it certainly still functions,
|
|
2
|
+
# I would advise that search commands be a bit more concise as most
|
|
3
|
+
# are only used in one location.
|
|
4
|
+
class StudySubjectSearch < Search
|
|
5
|
+
|
|
6
|
+
self.searchable_attributes += [ :races, :types, :vital_statuses, :q,
|
|
7
|
+
:sample_outcome, :interview_outcome,
|
|
8
|
+
:projects, :has_gift_card, :patid,
|
|
9
|
+
:abstracts_count
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
self.attr_accessors += [ :search_gift_cards, :abstracts_count ]
|
|
13
|
+
|
|
14
|
+
# self.valid_orders.merge!({ # NO!
|
|
15
|
+
# @valid_orders.merge!({ # NO!
|
|
16
|
+
self.valid_orders = self.valid_orders.merge({
|
|
17
|
+
:id => 'study_subjects.id', # must remove any possible ambiguity
|
|
18
|
+
:childid => 'childid',
|
|
19
|
+
:last_name => 'last_name',
|
|
20
|
+
:first_name => 'first_name',
|
|
21
|
+
:dob => 'dob',
|
|
22
|
+
:studyid => 'patid',
|
|
23
|
+
:priority => 'recruitment_priority',
|
|
24
|
+
:sample_outcome => 'homex_outcomes.sample_outcome_id',
|
|
25
|
+
:sample_outcome_on => 'homex_outcomes.sample_outcome_on',
|
|
26
|
+
:patid => 'patid',
|
|
27
|
+
:abstracts_count => nil,
|
|
28
|
+
:interview_outcome_on => 'homex_outcomes.interview_outcome_on',
|
|
29
|
+
:sample_sent_on => nil,
|
|
30
|
+
:sample_received_on => nil,
|
|
31
|
+
:number => 'gift_cards.number',
|
|
32
|
+
:issued_on => 'gift_cards.issued_on'
|
|
33
|
+
#
|
|
34
|
+
# TODO this isn't true no more. gotta add another join
|
|
35
|
+
#
|
|
36
|
+
# :sent_to_subject_on => 'samples.sent_to_subject_on',
|
|
37
|
+
# :received_by_ccls_at => 'samples.received_by_ccls_at'
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
def study_subjects
|
|
41
|
+
require_dependency 'gift_card.rb' unless GiftCard
|
|
42
|
+
@subjects ||= StudySubject.send(
|
|
43
|
+
(paginate?)?'paginate':'all',{
|
|
44
|
+
:select => select,
|
|
45
|
+
:group => group,
|
|
46
|
+
:having => having,
|
|
47
|
+
:order => search_order,
|
|
48
|
+
:joins => joins,
|
|
49
|
+
:conditions => conditions
|
|
50
|
+
}.merge(
|
|
51
|
+
(paginate?)?{
|
|
52
|
+
:per_page => per_page||25,
|
|
53
|
+
:page => page||1
|
|
54
|
+
}:{}
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
alias_method :subjects, :study_subjects
|
|
59
|
+
|
|
60
|
+
private # THIS IS REQUIRED
|
|
61
|
+
|
|
62
|
+
# TODO as is not true
|
|
63
|
+
# I don't think that sorting by these fields is ever done.
|
|
64
|
+
# def samples_joins
|
|
65
|
+
# "JOIN samples ON study_subjects.id " <<
|
|
66
|
+
# "= samples.study_subject_id" if %w( sent_to_subject_on received_by_ccls_at ).include?(@order)
|
|
67
|
+
# end
|
|
68
|
+
|
|
69
|
+
def vital_statuses_joins
|
|
70
|
+
"INNER JOIN vital_statuses ON vital_statuses.id " <<
|
|
71
|
+
"= study_subjects.vital_status_id" unless vital_statuses.blank?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def vital_statuses_conditions
|
|
75
|
+
['vital_statuses.key IN (:vital_statuses)', { :vital_statuses => vital_statuses }
|
|
76
|
+
] unless vital_statuses.blank?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def patid_conditions
|
|
80
|
+
['patid = :patid', {:patid => patid}] unless patid.blank?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def races_joins
|
|
85
|
+
# "INNER JOIN races ON races.id = study_subjects.race_id" unless races.blank?
|
|
86
|
+
"LEFT JOIN subject_races ON study_subjects.id = subject_races.study_subject_id LEFT JOIN races ON races.id = subject_races.race_id" unless races.blank?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#>> study_subjects = StudySubject.find(:all, :joins => "left join samples on study_subjects.id = samples.study_subject_id", :group => 'study_subjects.id', :having => ["sample_ids LIKE '%?%'",1], :select => "study_subjects.id, GROUP_CONCAT(samples.id) as sample_ids")
|
|
90
|
+
#=> [#<StudySubject id: 1>, #<StudySubject id: 2014>]
|
|
91
|
+
|
|
92
|
+
def races_groups
|
|
93
|
+
'study_subjects.id' unless races.blank?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def races_selects
|
|
97
|
+
"study_subjects.*, CONCAT('|',GROUP_CONCAT(races.description SEPARATOR '|'),'|') as race_descriptions" unless races.blank?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def races_havings
|
|
101
|
+
unless races.blank?
|
|
102
|
+
c = []
|
|
103
|
+
v = {}
|
|
104
|
+
races.each_with_index do |race,i|
|
|
105
|
+
c << "race_descriptions LIKE :r#{i}"
|
|
106
|
+
v["r#{i}".to_sym] = "%|#{race}|%"
|
|
107
|
+
end
|
|
108
|
+
[ c.join(' OR '), v ]
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def types_joins
|
|
114
|
+
"INNER JOIN subject_types ON subject_types.id " <<
|
|
115
|
+
"= study_subjects.subject_type_id" unless types.blank?
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def types_conditions
|
|
119
|
+
['subject_types.description IN (:types)', { :types => types }
|
|
120
|
+
] unless types.blank?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def gift_card_joins
|
|
124
|
+
# A study_subject has many gift cards so this may pose a problem
|
|
125
|
+
"LEFT JOIN gift_cards ON gift_cards.study_subject_id = study_subjects.id" if(
|
|
126
|
+
search_gift_cards || %w( number issued_on ).include?(@order))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def q_conditions
|
|
130
|
+
unless q.blank?
|
|
131
|
+
c = []
|
|
132
|
+
v = {}
|
|
133
|
+
q.to_s.split(/\s+/).each_with_index do |t,i|
|
|
134
|
+
c.push("first_name LIKE :t#{i}")
|
|
135
|
+
c.push("last_name LIKE :t#{i}")
|
|
136
|
+
c.push("patid LIKE :t#{i}")
|
|
137
|
+
c.push("childid LIKE :t#{i}")
|
|
138
|
+
c.push("gift_cards.number LIKE :t#{i}") if search_gift_cards
|
|
139
|
+
v["t#{i}".to_sym] = "%#{t}%"
|
|
140
|
+
end
|
|
141
|
+
[ "( #{c.join(' OR ')} )", v ]
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def gift_card_conditions
|
|
146
|
+
unless has_gift_card.nil?
|
|
147
|
+
if has_gift_card
|
|
148
|
+
["gift_cards.id IS NOT NULL"]
|
|
149
|
+
else
|
|
150
|
+
["gift_cards.id IS NULL"]
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# join order matters and this MUST come before
|
|
156
|
+
# those that join on home_outcomes! Hmm?
|
|
157
|
+
# How? Added a sort to joins and an "a_" to this
|
|
158
|
+
def a_homex_outcome_joins
|
|
159
|
+
"LEFT JOIN homex_outcomes ON homex_outcomes.study_subject_id " <<
|
|
160
|
+
"= study_subjects.id" if( !sample_outcome.blank? ||
|
|
161
|
+
!interview_outcome.blank? ||
|
|
162
|
+
[ 'sample_outcome','sample_outcome_on','interview_outcome_on'].include?(@order) )
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def sample_outcome_joins
|
|
166
|
+
"LEFT JOIN sample_outcomes ON sample_outcomes.id = " <<
|
|
167
|
+
"homex_outcomes.sample_outcome_id" unless
|
|
168
|
+
sample_outcome.blank?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def sample_outcome_conditions
|
|
172
|
+
unless sample_outcome.blank?
|
|
173
|
+
if sample_outcome =~ /^Complete$/i
|
|
174
|
+
# ['sample_outcomes.key = :sample_outcome',{:sample_outcome => sample_outcome}]
|
|
175
|
+
['sample_outcomes.key IS NOT NULL && sample_outcomes.key NOT IN ("Sent","Pending")']
|
|
176
|
+
else
|
|
177
|
+
["(sample_outcomes.key != 'Complete' " <<
|
|
178
|
+
"OR sample_outcomes.key IS NULL)"]
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def interview_outcome_joins
|
|
184
|
+
"LEFT JOIN interview_outcomes ON interview_outcomes.id = " <<
|
|
185
|
+
"homex_outcomes.interview_outcome_id" unless
|
|
186
|
+
interview_outcome.blank?
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def interview_outcome_conditions
|
|
190
|
+
unless interview_outcome.blank?
|
|
191
|
+
if interview_outcome =~ /^Complete$/i
|
|
192
|
+
['interview_outcomes.key = :interview_outcome', {:interview_outcome => interview_outcome}]
|
|
193
|
+
else
|
|
194
|
+
["(interview_outcomes.key != 'Complete'" <<
|
|
195
|
+
"OR interview_outcomes.key IS NULL)"]
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def projects_joins
|
|
201
|
+
unless projects.blank?
|
|
202
|
+
s = ''
|
|
203
|
+
projects.keys.each do |id|
|
|
204
|
+
s << "JOIN enrollments proj_#{id} ON study_subjects.id "<<
|
|
205
|
+
"= proj_#{id}.study_subject_id AND proj_#{id}.project_id = #{id} "
|
|
206
|
+
end
|
|
207
|
+
s
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def projects_conditions
|
|
212
|
+
unless projects.blank?
|
|
213
|
+
conditions = []
|
|
214
|
+
values = []
|
|
215
|
+
projects.each do |id,attributes|
|
|
216
|
+
attributes.each do |attr,val|
|
|
217
|
+
val = [val].flatten
|
|
218
|
+
if val.true_xor_false?
|
|
219
|
+
new_condition = case attr.to_s.downcase
|
|
220
|
+
when 'eligible'
|
|
221
|
+
"proj_#{id}.is_eligible " <<
|
|
222
|
+
((val.true?)?'= 1':'!= 1')
|
|
223
|
+
when 'candidate'
|
|
224
|
+
"proj_#{id}.is_candidate " <<
|
|
225
|
+
((val.true?)?'= 1':'!= 1')
|
|
226
|
+
when 'chosen'
|
|
227
|
+
"proj_#{id}.is_chosen " <<
|
|
228
|
+
((val.true?)?'= 1':'!= 1')
|
|
229
|
+
when 'consented'
|
|
230
|
+
"proj_#{id}.consented " <<
|
|
231
|
+
((val.true?)?'= 1':'!= 1')
|
|
232
|
+
when 'terminated'
|
|
233
|
+
"proj_#{id}.terminated_participation " <<
|
|
234
|
+
((val.true?)?'= 1':'!= 1')
|
|
235
|
+
when 'closed'
|
|
236
|
+
"proj_#{id}.is_closed " <<
|
|
237
|
+
((val.true?)?'= 1':'!= 1')
|
|
238
|
+
when 'completed'
|
|
239
|
+
"proj_#{id}.completed_on IS " <<
|
|
240
|
+
((val.true?)?'NOT NULL':'NULL')
|
|
241
|
+
end # case attr.to_s.downcase
|
|
242
|
+
conditions << new_condition unless new_condition.blank?
|
|
243
|
+
end # if val.true_xor_false?
|
|
244
|
+
end # attributes.each
|
|
245
|
+
end # projects.each
|
|
246
|
+
[conditions.compact,values].flatten(1) unless conditions.empty?
|
|
247
|
+
end # unless projects.blank?
|
|
248
|
+
end # def projects_conditions
|
|
249
|
+
|
|
250
|
+
def abstracts_count_conditions
|
|
251
|
+
unless @abstracts_count.blank?
|
|
252
|
+
case @abstracts_count.to_s
|
|
253
|
+
when '0' then ["abstracts_count <= 0"]
|
|
254
|
+
when '1' then ["abstracts_count = 1"]
|
|
255
|
+
when '2' then ["abstracts_count = 2"]
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Simply extracted some code to clean up model.
|
|
3
|
+
# I'd like to do this to all of the really big classes
|
|
4
|
+
# but let's see how this goes first.
|
|
5
|
+
#
|
|
6
|
+
module StudySubjectValidations
|
|
7
|
+
def self.included(base)
|
|
8
|
+
# Must delay the calls to these ActiveRecord methods
|
|
9
|
+
# or it will raise many "undefined method"s.
|
|
10
|
+
base.class_eval do
|
|
11
|
+
|
|
12
|
+
validates_presence_of :subject_type_id
|
|
13
|
+
validates_presence_of :subject_type, :if => :subject_type_id
|
|
14
|
+
|
|
15
|
+
validate :presence_of_sex
|
|
16
|
+
# validates_inclusion_of :sex, :in => %w( M F DK ), :allow_blank => true
|
|
17
|
+
validates_inclusion_of :sex, :in => valid_sex_values, :allow_blank => true
|
|
18
|
+
validates_inclusion_of :do_not_contact, :in => [ true, false ]
|
|
19
|
+
|
|
20
|
+
validates_complete_date_for :reference_date, :allow_nil => true
|
|
21
|
+
|
|
22
|
+
validate :presence_of_dob, :unless => :is_mother?
|
|
23
|
+
validates_complete_date_for :dob, :allow_nil => true
|
|
24
|
+
validates_past_date_for :dob, :allow_nil => true
|
|
25
|
+
validates_complete_date_for :died_on, :allow_nil => true
|
|
26
|
+
validates_uniqueness_of :email, :icf_master_id, :state_id_no,
|
|
27
|
+
:state_registrar_no, :local_registrar_no, :gbid, :lab_no_wiemels,
|
|
28
|
+
:accession_no, :idno_wiemels, :studyid, :allow_nil => true
|
|
29
|
+
|
|
30
|
+
validates_format_of :email,
|
|
31
|
+
:with => /\A([-a-z0-9!\#$%&'*+\/=?^_`{|}~]+\.)*[-a-z0-9!\#$%&'*+\/=?^_`{|}~]+@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
|
|
32
|
+
:allow_blank => true
|
|
33
|
+
|
|
34
|
+
validate :presence_of_guardian_relationship_other,
|
|
35
|
+
:if => :guardian_relationship_is_other?
|
|
36
|
+
|
|
37
|
+
validates_presence_of :birth_city,
|
|
38
|
+
:if => :birth_country_is_united_states?
|
|
39
|
+
validates_presence_of :birth_state,
|
|
40
|
+
:if => :birth_country_is_united_states?
|
|
41
|
+
|
|
42
|
+
validates_length_of :case_control_type, :is => 1, :allow_nil => true
|
|
43
|
+
|
|
44
|
+
validates_length_of :ssn, :maximum => 250, :allow_nil => true
|
|
45
|
+
validates_uniqueness_of :ssn, :allow_nil => true
|
|
46
|
+
validates_format_of :ssn, :with => /\A\d{3}-\d{2}-\d{4}\z/,
|
|
47
|
+
:message => "should be formatted ###-##-####", :allow_nil => true
|
|
48
|
+
|
|
49
|
+
validates_length_of :birth_year,
|
|
50
|
+
:maximum => 4, :allow_blank => true
|
|
51
|
+
validates_length_of :newid,
|
|
52
|
+
:maximum => 6, :allow_blank => true
|
|
53
|
+
validates_length_of :icf_master_id,
|
|
54
|
+
:maximum => 9, :allow_blank => true
|
|
55
|
+
validates_length_of :childidwho, :idno_wiemels,
|
|
56
|
+
:generational_suffix, :father_generational_suffix,
|
|
57
|
+
:maximum => 10, :allow_blank => true
|
|
58
|
+
validates_length_of :lab_no_wiemels, :accession_no,
|
|
59
|
+
:maximum => 25, :allow_blank => true
|
|
60
|
+
validates_length_of :gbid,
|
|
61
|
+
:maximum => 26, :allow_blank => true
|
|
62
|
+
validates_length_of :first_name, :last_name,
|
|
63
|
+
:middle_name, :maiden_name, :guardian_relationship_other,
|
|
64
|
+
:father_first_name, :father_middle_name, :father_last_name,
|
|
65
|
+
:mother_first_name, :mother_middle_name, :mother_maiden_name, :mother_last_name,
|
|
66
|
+
:guardian_first_name, :guardian_middle_name, :guardian_last_name,
|
|
67
|
+
:mother_race_other, :father_race_other,
|
|
68
|
+
:birth_city, :birth_state, :birth_country,
|
|
69
|
+
:state_id_no, :state_registrar_no, :local_registrar_no,
|
|
70
|
+
:lab_no, :related_childid, :related_case_childid,
|
|
71
|
+
:maximum => 250, :allow_blank => true
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
validates_inclusion_of :mom_is_biomom, :dad_is_biodad,
|
|
75
|
+
:in => YNDK.valid_values, :allow_nil => true
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# custom validation for custom message without standard attribute prefix
|
|
79
|
+
def presence_of_sex
|
|
80
|
+
if sex.blank?
|
|
81
|
+
errors.add(:sex, ActiveRecord::Error.new(
|
|
82
|
+
self, :base, :blank, {
|
|
83
|
+
:message => "No sex has been chosen." } ) )
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
protected
|
|
88
|
+
|
|
89
|
+
def birth_country_is_united_states?
|
|
90
|
+
birth_country == 'United States'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# custom validation for custom message without standard attribute prefix
|
|
94
|
+
def presence_of_guardian_relationship_other
|
|
95
|
+
if guardian_relationship_other.blank?
|
|
96
|
+
errors.add(:guardian_relationship_other, ActiveRecord::Error.new(
|
|
97
|
+
self, :base, :blank, {
|
|
98
|
+
:message => "You must specify a relationship with 'other relationship' is selected." } ) )
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# custom validation for custom message without standard attribute prefix
|
|
103
|
+
def presence_of_dob
|
|
104
|
+
if dob.blank?
|
|
105
|
+
errors.add(:dob, ActiveRecord::Error.new(
|
|
106
|
+
self, :base, :blank, {
|
|
107
|
+
:message => "Date of birth can't be blank." } ) )
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end # class_eval
|
|
112
|
+
end # included
|
|
113
|
+
end # StudySubjectValidations
|
|
114
|
+
|
|
115
|
+
__END__
|
|
116
|
+
|