ccls-ccls_engine 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|