clinical 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +8 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +87 -0
- data/VERSION +1 -0
- data/clinical.gemspec +81 -0
- data/features/finding_clinical_trials.feature +52 -0
- data/features/getting_keywords_and_categories.feature +9 -0
- data/features/step_definitions/clinical_steps.rb +74 -0
- data/features/support/env.rb +6 -0
- data/lib/clinical/address.rb +10 -0
- data/lib/clinical/agency.rb +6 -0
- data/lib/clinical/collaborator.rb +6 -0
- data/lib/clinical/collection.rb +24 -0
- data/lib/clinical/condition.rb +20 -0
- data/lib/clinical/contact.rb +13 -0
- data/lib/clinical/extensions.rb +28 -0
- data/lib/clinical/intervention.rb +13 -0
- data/lib/clinical/lead_sponsor.rb +6 -0
- data/lib/clinical/location.rb +10 -0
- data/lib/clinical/outcome.rb +29 -0
- data/lib/clinical/primary_outcome.rb +6 -0
- data/lib/clinical/secondary_outcome.rb +6 -0
- data/lib/clinical/sponsor.rb +27 -0
- data/lib/clinical/status.rb +42 -0
- data/lib/clinical/trial.rb +181 -0
- data/lib/clinical.rb +29 -0
- data/test/clinical/trial_test.rb +48 -0
- data/test/fixtures/lupus_single.xml +171 -0
- data/test/fixtures/open_set.xml +212 -0
- data/test/test_helper.rb +23 -0
- metadata +127 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Dan Pickett
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin require "metric_fu" rescue LoadError; end
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "clinical"
|
10
|
+
gem.summary = %Q{a library for accessing data from ClinicalTrials.gov}
|
11
|
+
gem.email = "dpickett@enlightsolutions.com"
|
12
|
+
gem.homepage = "http://github.com/dpickett/clinical"
|
13
|
+
gem.authors = ["Dan Pickett"]
|
14
|
+
gem.add_dependency("jnunemaker-httparty", ">= 0.4.3")
|
15
|
+
gem.add_dependency("jnunemaker-happymapper", ">= 0.2.5")
|
16
|
+
gem.add_dependency("mislav-will_paginate", ">= 2.3.11")
|
17
|
+
gem.add_dependency("nokogiri", ">= 1.3.3")
|
18
|
+
|
19
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'rake/testtask'
|
27
|
+
Rake::TestTask.new(:test) do |test|
|
28
|
+
test.libs << 'lib' << 'test'
|
29
|
+
test.pattern = 'test/**/*_test.rb'
|
30
|
+
test.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace :rcov do
|
34
|
+
require 'rcov/rcovtask'
|
35
|
+
Rcov::RcovTask.new(:tests) do |test|
|
36
|
+
test.libs << 'test'
|
37
|
+
test.pattern = 'test/**/*_test.rb'
|
38
|
+
test.rcov_opts = %w{--aggregate coverage.data --exclude osx\/objc,gems\/,spec\/}
|
39
|
+
test.verbose = true
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'cucumber/rake/task'
|
43
|
+
Cucumber::Rake::Task.new(:cucumber) do |t|
|
44
|
+
t.rcov = true
|
45
|
+
t.rcov_opts = %w{--aggregate coverage.data --exclude osx\/objc,gems\/,features\/,spec\/ -o "features_rcov"}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
begin
|
49
|
+
desc "Run both specs and features to generate aggregated coverage"
|
50
|
+
task :rcov do |t|
|
51
|
+
rm "coverage.data" if File.exist?("coverage.data")
|
52
|
+
Rake::Task["rcov:cucumber"].invoke
|
53
|
+
Rake::Task["rcov:tests"].invoke
|
54
|
+
end
|
55
|
+
rescue LoadError
|
56
|
+
task :rcov do
|
57
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
begin
|
62
|
+
require 'cucumber/rake/task'
|
63
|
+
Cucumber::Rake::Task.new(:features)
|
64
|
+
|
65
|
+
rescue LoadError
|
66
|
+
task :features do
|
67
|
+
abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
task :default => :test
|
72
|
+
|
73
|
+
require 'rake/rdoctask'
|
74
|
+
Rake::RDocTask.new do |rdoc|
|
75
|
+
if File.exist?('VERSION.yml')
|
76
|
+
config = YAML.load(File.read('VERSION.yml'))
|
77
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
78
|
+
else
|
79
|
+
version = ""
|
80
|
+
end
|
81
|
+
|
82
|
+
rdoc.rdoc_dir = 'rdoc'
|
83
|
+
rdoc.title = "clinical #{version}"
|
84
|
+
rdoc.rdoc_files.include('README*')
|
85
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
86
|
+
end
|
87
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.2
|
data/clinical.gemspec
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{clinical}
|
5
|
+
s.version = "0.2.2"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Dan Pickett"]
|
9
|
+
s.date = %q{2009-07-28}
|
10
|
+
s.email = %q{dpickett@enlightsolutions.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"LICENSE",
|
13
|
+
"README.rdoc"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
".document",
|
17
|
+
".gitignore",
|
18
|
+
"LICENSE",
|
19
|
+
"README.rdoc",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"clinical.gemspec",
|
23
|
+
"features/finding_clinical_trials.feature",
|
24
|
+
"features/getting_keywords_and_categories.feature",
|
25
|
+
"features/step_definitions/clinical_steps.rb",
|
26
|
+
"features/support/env.rb",
|
27
|
+
"lib/clinical.rb",
|
28
|
+
"lib/clinical/address.rb",
|
29
|
+
"lib/clinical/agency.rb",
|
30
|
+
"lib/clinical/collaborator.rb",
|
31
|
+
"lib/clinical/collection.rb",
|
32
|
+
"lib/clinical/condition.rb",
|
33
|
+
"lib/clinical/contact.rb",
|
34
|
+
"lib/clinical/extensions.rb",
|
35
|
+
"lib/clinical/intervention.rb",
|
36
|
+
"lib/clinical/lead_sponsor.rb",
|
37
|
+
"lib/clinical/location.rb",
|
38
|
+
"lib/clinical/outcome.rb",
|
39
|
+
"lib/clinical/primary_outcome.rb",
|
40
|
+
"lib/clinical/secondary_outcome.rb",
|
41
|
+
"lib/clinical/sponsor.rb",
|
42
|
+
"lib/clinical/status.rb",
|
43
|
+
"lib/clinical/trial.rb",
|
44
|
+
"test/clinical/trial_test.rb",
|
45
|
+
"test/fixtures/lupus_single.xml",
|
46
|
+
"test/fixtures/open_set.xml",
|
47
|
+
"test/test_helper.rb"
|
48
|
+
]
|
49
|
+
s.has_rdoc = true
|
50
|
+
s.homepage = %q{http://github.com/dpickett/clinical}
|
51
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
52
|
+
s.require_paths = ["lib"]
|
53
|
+
s.rubygems_version = %q{1.3.2}
|
54
|
+
s.summary = %q{a library for accessing data from ClinicalTrials.gov}
|
55
|
+
s.test_files = [
|
56
|
+
"test/clinical/trial_test.rb",
|
57
|
+
"test/test_helper.rb"
|
58
|
+
]
|
59
|
+
|
60
|
+
if s.respond_to? :specification_version then
|
61
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
62
|
+
s.specification_version = 3
|
63
|
+
|
64
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
65
|
+
s.add_runtime_dependency(%q<jnunemaker-httparty>, [">= 0.4.3"])
|
66
|
+
s.add_runtime_dependency(%q<jnunemaker-happymapper>, [">= 0.2.5"])
|
67
|
+
s.add_runtime_dependency(%q<mislav-will_paginate>, [">= 2.3.11"])
|
68
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 1.3.3"])
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<jnunemaker-httparty>, [">= 0.4.3"])
|
71
|
+
s.add_dependency(%q<jnunemaker-happymapper>, [">= 0.2.5"])
|
72
|
+
s.add_dependency(%q<mislav-will_paginate>, [">= 2.3.11"])
|
73
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<jnunemaker-httparty>, [">= 0.4.3"])
|
77
|
+
s.add_dependency(%q<jnunemaker-happymapper>, [">= 0.2.5"])
|
78
|
+
s.add_dependency(%q<mislav-will_paginate>, [">= 2.3.11"])
|
79
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
Feature: As a potential participant for a clinical study
|
2
|
+
I want to search for clinical trials
|
3
|
+
So that I can find out more information about them
|
4
|
+
|
5
|
+
Scenario: Find open studies
|
6
|
+
Given I am searching for trials where "recruiting" is "true"
|
7
|
+
When I perform the search
|
8
|
+
Then I should get trials that are "open"
|
9
|
+
|
10
|
+
Scenario: Find closed studies
|
11
|
+
Given I am searching for trials where "recruiting" is "false"
|
12
|
+
When I perform the search
|
13
|
+
Then I should get trials that are not "open"
|
14
|
+
|
15
|
+
Scenario: Find a specific condition
|
16
|
+
Given I am searching for trials where "condition" is "hemophelia"
|
17
|
+
When I perform the extended search
|
18
|
+
Then I should get trials where the "conditions" contains "hemophelia"
|
19
|
+
|
20
|
+
Scenario: Find a specific intervention
|
21
|
+
Given I am searching for trials where "intervention" is "drug"
|
22
|
+
When I perform the extended search
|
23
|
+
Then I should get trials where the "interventions" contains "drug"
|
24
|
+
|
25
|
+
Scenario: Find a specific outcome
|
26
|
+
Given I am searching for trials where "outcome" is "toxic"
|
27
|
+
When I perform the extended search
|
28
|
+
Then I should get trials where the "outcomes" contains "toxic"
|
29
|
+
|
30
|
+
Scenario: Find a specific sponsor
|
31
|
+
Given I am searching for trials where "sponsor" is "Eli Lilly"
|
32
|
+
When I perform the extended search
|
33
|
+
Then I should get trials where the "sponsors" contains "Eli Lilly"
|
34
|
+
|
35
|
+
Scenario: Find a specific trial
|
36
|
+
When I attempt to retrieve trial "NCT00001372"
|
37
|
+
Then I should get a trial
|
38
|
+
And the trial should have an "id" of "NCT00001372"
|
39
|
+
|
40
|
+
Scenario: Find a specific trial with extended attributes
|
41
|
+
When I attempt to retrieve trial "NCT00454363"
|
42
|
+
Then I should get a trial
|
43
|
+
And the trial should have a "phase" of "2"
|
44
|
+
And the trial should have "conditions" like "Lung Cancer"
|
45
|
+
And the trial should have a "minimum_age" of "21 Years"
|
46
|
+
And the trial should have "sponsors" like "M.D. Anderson"
|
47
|
+
|
48
|
+
Scenario: Find a non-existant trial
|
49
|
+
When I attempt to retrieve trial "4325785"
|
50
|
+
Then I should not get a trial
|
51
|
+
|
52
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Feature: As a user of the clinical library
|
2
|
+
I want to retrieve keywords, categories, and terms from ClinicalTrials.gov
|
3
|
+
So that I can associate related trials
|
4
|
+
|
5
|
+
Scenario: Get keywords, categories, and terms
|
6
|
+
When I attempt to retrieve keywords for trial "NCT00001372"
|
7
|
+
Then the trial should have "keywords" like "Autoimmunity"
|
8
|
+
And the trial should have "categories" like "Urologic Diseases"
|
9
|
+
And the trial should have "terms" like "Connective Tissue Diseases"
|
@@ -0,0 +1,74 @@
|
|
1
|
+
Given /^I am searching for trials where "([^\"]*)" is "([^\"]*)"$/ do |field, value|
|
2
|
+
@params ||= {}
|
3
|
+
|
4
|
+
if value == "true"
|
5
|
+
value = true
|
6
|
+
elsif value == "false"
|
7
|
+
value = false
|
8
|
+
end
|
9
|
+
|
10
|
+
@params[field.to_sym] = value
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I perform the search$/ do
|
14
|
+
@trials = Clinical::Trial.find(:conditions => @params)
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I perform the extended search$/ do
|
18
|
+
@trials = Clinical::Trial.find(:conditions => @params, :extended => true)
|
19
|
+
end
|
20
|
+
|
21
|
+
When /^I attempt to retrieve trial "([^\"]*)"$/ do |id|
|
22
|
+
@trial = Clinical::Trial.find_by_id(id)
|
23
|
+
end
|
24
|
+
|
25
|
+
When /^I attempt to retrieve keywords for trial "([^\"]*)"$/ do |id|
|
26
|
+
@trial = Clinical::Trial.find_by_id(id)
|
27
|
+
@trial.get_metadata
|
28
|
+
end
|
29
|
+
|
30
|
+
Then /^I should get trials that are (not )?"([^\"]*)"$/ do |not_included, field|
|
31
|
+
if not_included
|
32
|
+
result = false
|
33
|
+
else
|
34
|
+
result = true
|
35
|
+
end
|
36
|
+
|
37
|
+
@trials.each do |trial|
|
38
|
+
trial.send(field + "?").should(eql(result))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Then /^I should get trials where the "([^\"]*)" contains "([^\"]*)"$/ do |field, value|
|
43
|
+
@trials.each do |trial|
|
44
|
+
item_values = []
|
45
|
+
result = trial.send(field)
|
46
|
+
if result.is_a?(Array)
|
47
|
+
found = false
|
48
|
+
result.each do |i|
|
49
|
+
found = true if i.to_s =~ /#{value}/i
|
50
|
+
end
|
51
|
+
found.should be_true
|
52
|
+
else
|
53
|
+
result.to_s.should =~ /#{value}/i
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Then /^I should get a trial$/ do
|
59
|
+
@trial.should_not be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
Then /^the trial should have an? "([^\"]*)" of "([^\"]*)"$/ do |field, value|
|
63
|
+
@trial.send(field).to_s.should eql(value)
|
64
|
+
end
|
65
|
+
|
66
|
+
Then /^the trial should have "([^\"]*)" like "([^\"]*)"$/ do |field, value|
|
67
|
+
@trial.send(field).to_s.should =~ /#{Regexp.escape(value)}/
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
Then /^I should not get a trial$/ do
|
72
|
+
@trial.should be_nil
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Clinical
|
2
|
+
class Collection < WillPaginate::Collection
|
3
|
+
include HappyMapper
|
4
|
+
attr_accessor :count
|
5
|
+
class << self
|
6
|
+
def create_from_results(page, per_page, body)
|
7
|
+
results = SearchResult.parse(body)
|
8
|
+
col = create(page, per_page, results.count || 0) do |pager|
|
9
|
+
pager.replace(results.trials)
|
10
|
+
end
|
11
|
+
col.count = results.count
|
12
|
+
col
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class SearchResult
|
17
|
+
include HappyMapper
|
18
|
+
tag "search_results"
|
19
|
+
attribute "count", Integer
|
20
|
+
|
21
|
+
has_many :trials, Clinical::Trial
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Clinical
|
2
|
+
class Condition
|
3
|
+
attr_accessor :name
|
4
|
+
include HappyMapper
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
self.name || ""
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def parse(xml, options)
|
12
|
+
xml.find("condition").collect do |n|
|
13
|
+
item = new
|
14
|
+
item.name = n.content.chomp.strip
|
15
|
+
item
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Clinical
|
2
|
+
class Contact
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
element :first_name, String
|
6
|
+
element :middle_name, String
|
7
|
+
element :last_name, String
|
8
|
+
element :degrees, String
|
9
|
+
element :phone, String
|
10
|
+
element :phone_ext, String
|
11
|
+
element :email, String
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#thanks Rails Core!
|
2
|
+
module Clinical
|
3
|
+
module Extensions
|
4
|
+
module Array
|
5
|
+
def extract_options!
|
6
|
+
last.is_a?(::Hash) ? pop : {}
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module String
|
12
|
+
def underscore(camel_cased_word)
|
13
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
14
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
15
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
16
|
+
tr("-", "_").
|
17
|
+
downcase
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
unless String.instance_methods.include?("underscore")
|
24
|
+
String.send(:include, Clinical::Extensions::String)
|
25
|
+
end
|
26
|
+
unless Array.instance_methods.include?("extract_options!")
|
27
|
+
Array.send(:include, Clinical::Extensions::Array)
|
28
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Clinical
|
2
|
+
class Intervention
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
element :type, String, :tag => "intervention_type"
|
6
|
+
element :description, String
|
7
|
+
element :name, String, :tag => "intervention_name"
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"#{self.name} (#{self.type}): #{self.description}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Clinical
|
2
|
+
module Outcome
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
base.class_eval do
|
7
|
+
include InstanceMethods
|
8
|
+
include HappyMapper
|
9
|
+
element :measure, String
|
10
|
+
element :time_frame, String
|
11
|
+
element :safety_issue, String
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module InstanceMethods
|
16
|
+
def primary?
|
17
|
+
self.class.tag_name == "primary_outcome"
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
val = "#{measure}"
|
22
|
+
val << ", TIME FRAME: #{time_frame}" if time_frame
|
23
|
+
val << ",SAFETY ISSUE: #{safety_issue}" if safety_issue
|
24
|
+
val
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Clinical
|
2
|
+
module Sponsor
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
attr_accessor :name
|
6
|
+
include HappyMapper
|
7
|
+
end
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
base.send(:include, InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def to_s
|
14
|
+
name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
module ClassMethods
|
18
|
+
def parse(xml, options = {})
|
19
|
+
xml.find(tag_name).collect do |n|
|
20
|
+
item = new
|
21
|
+
item.name = n.content.chomp.strip
|
22
|
+
item
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Clinical
|
2
|
+
class Status
|
3
|
+
STATUSES = [
|
4
|
+
:not_yet_recruiting,
|
5
|
+
:recruiting,
|
6
|
+
:enrolling_by_invitation,
|
7
|
+
:active,
|
8
|
+
:not_recruiting,
|
9
|
+
:completed,
|
10
|
+
:suspended,
|
11
|
+
:terminated,
|
12
|
+
:withdrawn,
|
13
|
+
:available,
|
14
|
+
:no_longer_available
|
15
|
+
]
|
16
|
+
|
17
|
+
OPEN_STATUSES = [
|
18
|
+
:not_yet_recruiting,
|
19
|
+
:recruiting
|
20
|
+
]
|
21
|
+
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
def initialize(sym)
|
25
|
+
@name = sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def open?
|
29
|
+
OPEN_STATUSES.include?(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
@name.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def parse(s)
|
38
|
+
s.nil? ? nil : Status.new(s.downcase.gsub(" ", "_").to_sym)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|