caruby-small 1.1.2
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/.gitignore +20 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +106 -0
- data/History.md +9 -0
- data/LEGAL +5 -0
- data/LICENSE +22 -0
- data/README.md +55 -0
- data/Rakefile +36 -0
- data/bin/casmall +7 -0
- data/caruby-small.gemspec +30 -0
- data/config.ru +12 -0
- data/lib/casmall/authorization.rb +80 -0
- data/lib/casmall/version.rb +3 -0
- data/lib/casmall/web_service.rb +66 -0
- data/lib/casmall.rb +52 -0
- data/spec/create_spec.rb +33 -0
- data/spec/find_spec.rb +26 -0
- data/spec/query_spec.rb +36 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/rack_test.rb +16 -0
- data/spec/update_spec.rb +37 -0
- metadata +167 -0
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
.DS_Store
|
2
|
+
*~
|
3
|
+
*.pdf
|
4
|
+
*.tmproj
|
5
|
+
.project
|
6
|
+
.loadpath
|
7
|
+
.yardoc
|
8
|
+
/.bundle
|
9
|
+
*.gem
|
10
|
+
*.tar*
|
11
|
+
/ext
|
12
|
+
/doc/api
|
13
|
+
**log
|
14
|
+
/test/config
|
15
|
+
/test/results
|
16
|
+
/embed/gems
|
17
|
+
/embed/staging
|
18
|
+
/embed/target
|
19
|
+
/embed/classes
|
20
|
+
/embed/lib/*.jar
|
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source :rubygems
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
# Uncomment the following lines if there are local gem changes. Change the path option
|
6
|
+
# to your workspace location. Commit the changed Gemfile and Gemfile.lock to a git branch
|
7
|
+
# named 'local' rather than to the master branch. Do not check in the local change.
|
8
|
+
gem 'caruby-core', :path => File.dirname(__FILE__) + '/../core'
|
9
|
+
gem 'caruby-tissue', :path => File.dirname(__FILE__) + '/../tissue'
|
10
|
+
gem 'jinx', :path => File.dirname(__FILE__) + '/../../jinx/core'
|
11
|
+
gem 'jinx-migrate', :path => File.dirname(__FILE__) + '/../../jinx/migrate'
|
12
|
+
gem 'jinx-json', :path => File.dirname(__FILE__) + '/../../jinx/json'
|
13
|
+
gem 'caruby-small', :path => File.dirname(__FILE__)
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem 'rspec', '>= 2.6'
|
18
|
+
gem 'sinatra', '=1.2.6'
|
19
|
+
gem 'rack-test', :require => 'rack/test'
|
20
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
caruby-small (1.1.2)
|
5
|
+
bundler
|
6
|
+
caruby-tissue (>= 2.1.4)
|
7
|
+
jruby-openssl
|
8
|
+
rack
|
9
|
+
sinatra
|
10
|
+
sinatra-authorization
|
11
|
+
|
12
|
+
PATH
|
13
|
+
remote: /Users/loneyf/workspace/caruby/core
|
14
|
+
specs:
|
15
|
+
caruby-core (2.1.3)
|
16
|
+
bundler
|
17
|
+
jinx (~> 2.1.1)
|
18
|
+
jinx-json (~> 2.1.1)
|
19
|
+
jinx-migrate (>= 2.1.1)
|
20
|
+
rdbi
|
21
|
+
|
22
|
+
PATH
|
23
|
+
remote: /Users/loneyf/workspace/caruby/tissue
|
24
|
+
specs:
|
25
|
+
caruby-tissue (2.1.5)
|
26
|
+
bundler
|
27
|
+
caruby-core (>= 2.1.1)
|
28
|
+
uom (>= 1.2.2)
|
29
|
+
|
30
|
+
PATH
|
31
|
+
remote: /Users/loneyf/workspace/jinx/core
|
32
|
+
specs:
|
33
|
+
jinx (2.1.3)
|
34
|
+
bundler
|
35
|
+
|
36
|
+
PATH
|
37
|
+
remote: /Users/loneyf/workspace/jinx/json
|
38
|
+
specs:
|
39
|
+
jinx-json (2.1.2)
|
40
|
+
bundler
|
41
|
+
jinx
|
42
|
+
json_pure
|
43
|
+
|
44
|
+
PATH
|
45
|
+
remote: /Users/loneyf/workspace/jinx/migrate
|
46
|
+
specs:
|
47
|
+
jinx-migrate (2.1.2)
|
48
|
+
bundler
|
49
|
+
fastercsv
|
50
|
+
rack
|
51
|
+
|
52
|
+
GEM
|
53
|
+
remote: http://rubygems.org/
|
54
|
+
specs:
|
55
|
+
bouncy-castle-java (1.5.0146.1)
|
56
|
+
diff-lcs (1.1.3)
|
57
|
+
epoxy (0.3.1)
|
58
|
+
extensional (1.3.1)
|
59
|
+
fastercsv (1.5.5)
|
60
|
+
jruby-openssl (0.7.7)
|
61
|
+
bouncy-castle-java (>= 1.5.0146.1)
|
62
|
+
json_pure (1.7.3)
|
63
|
+
methlab (0.1.0)
|
64
|
+
rack (1.4.1)
|
65
|
+
rack-test (0.6.1)
|
66
|
+
rack (>= 1.0)
|
67
|
+
rake (0.9.2.2)
|
68
|
+
rdbi (0.9.1)
|
69
|
+
epoxy (>= 0.3.1)
|
70
|
+
methlab (>= 0.0.9)
|
71
|
+
typelib
|
72
|
+
rspec (2.10.0)
|
73
|
+
rspec-core (~> 2.10.0)
|
74
|
+
rspec-expectations (~> 2.10.0)
|
75
|
+
rspec-mocks (~> 2.10.0)
|
76
|
+
rspec-core (2.10.1)
|
77
|
+
rspec-expectations (2.10.0)
|
78
|
+
diff-lcs (~> 1.1.3)
|
79
|
+
rspec-mocks (2.10.1)
|
80
|
+
sinatra (1.2.6)
|
81
|
+
rack (~> 1.1)
|
82
|
+
tilt (>= 1.2.2, < 2.0)
|
83
|
+
sinatra-authorization (1.0.0)
|
84
|
+
sinatra (>= 0.9.1.1)
|
85
|
+
tilt (1.3.3)
|
86
|
+
typelib (0.1.0)
|
87
|
+
uom (1.2.2)
|
88
|
+
extensional
|
89
|
+
yard (0.8.2.1)
|
90
|
+
|
91
|
+
PLATFORMS
|
92
|
+
java
|
93
|
+
ruby
|
94
|
+
|
95
|
+
DEPENDENCIES
|
96
|
+
caruby-core!
|
97
|
+
caruby-small!
|
98
|
+
caruby-tissue!
|
99
|
+
jinx!
|
100
|
+
jinx-json!
|
101
|
+
jinx-migrate!
|
102
|
+
rack-test
|
103
|
+
rake
|
104
|
+
rspec (>= 2.6)
|
105
|
+
sinatra (= 1.2.6)
|
106
|
+
yard
|
data/History.md
ADDED
data/LEGAL
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Oregon Health & Science University
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
ca<small>Small</small>: A caTissue web service and application micro-framework
|
2
|
+
==============================================================================
|
3
|
+
**Home**: [http://caruby.rubyforge.org/casmall.html](http://caruby.rubyforge.org/casmall.html)
|
4
|
+
**Git**: [http://github.com/caruby/small](http://github.com/caruby/small)
|
5
|
+
**Author**: OHSU Knight Cancer Institute
|
6
|
+
**Copyright**: 2012
|
7
|
+
**License**: MIT License
|
8
|
+
|
9
|
+
Synopsis
|
10
|
+
--------
|
11
|
+
caSmall is a framework for deploying a caTissue RESTful web service and custom web applications.
|
12
|
+
This project features a web service. The companion [Scat](http://github.com/caruby/scat) project
|
13
|
+
is a light-weight web application.
|
14
|
+
|
15
|
+
Feature List
|
16
|
+
------------
|
17
|
+
1. Search, create and update caTissue objects.
|
18
|
+
|
19
|
+
2. Leverages the [caRuby](http://caruby.rubyforge.org) declarative API.
|
20
|
+
|
21
|
+
Installing
|
22
|
+
----------
|
23
|
+
caSmall is installed on a server as a JRuby gem:
|
24
|
+
sudo jgem install caruby-small
|
25
|
+
|
26
|
+
Usage
|
27
|
+
-----
|
28
|
+
Examples:
|
29
|
+
|
30
|
+
* Fetch the specimen with identifier 212:
|
31
|
+
|
32
|
+
GET `myserver:9060/casmall/specimen/212`
|
33
|
+
|
34
|
+
* Fetch the specimen collection group with SPN <tt>SPN-41873</tt>:
|
35
|
+
|
36
|
+
GET `myserver:9060/casmall/SpecimenCollectionGroup?surgicalPathologyNumber=SPN-41873`
|
37
|
+
|
38
|
+
* Fetch specimens based on a submitted JSON criterion template:
|
39
|
+
|
40
|
+
POST `myserver:9060/casmall/query`
|
41
|
+
|
42
|
+
* Create a specimen from a submitted JSON object:
|
43
|
+
|
44
|
+
POST `myserver:9060/casmall/`
|
45
|
+
|
46
|
+
* Update a specimen from a submitted JSON object:
|
47
|
+
|
48
|
+
PUT `myserver:9060/casmall/`
|
49
|
+
|
50
|
+
The JSON payload is described in the Jinx [JSON](http://github.com/jinx/json) project.
|
51
|
+
|
52
|
+
Copyright
|
53
|
+
---------
|
54
|
+
caSmall © 2012 by [Oregon Health & Science University](http://www.ohsu.edu/xd/health/services/cancer).
|
55
|
+
caSmall is licensed under the MIT license. Please see the LICENSE and LEGAL files for more information.
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require File.expand_path('version', File.dirname(__FILE__) + '/lib/casmall')
|
3
|
+
|
4
|
+
desc "Default: run all tests"
|
5
|
+
task :default => :test
|
6
|
+
|
7
|
+
# the gem name
|
8
|
+
GEM = 'caruby-small'
|
9
|
+
GEM_VERSION = CaSmall::VERSION
|
10
|
+
|
11
|
+
WINDOWS = (Config::CONFIG['host_os'] =~ /mingw|win32|cygwin/ ? true : false) rescue false
|
12
|
+
SUDO = WINDOWS ? '' : 'sudo'
|
13
|
+
|
14
|
+
desc 'Builds the gem'
|
15
|
+
task :gem do
|
16
|
+
sh "jgem build #{GEM}.gemspec"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Installs the gem'
|
20
|
+
task :install => :gem do
|
21
|
+
sh "#{SUDO} jgem install #{GEM}-#{GEM_VERSION}.gem"
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Documents the API'
|
25
|
+
task :doc do
|
26
|
+
FileUtils.rm_rf 'doc/api'
|
27
|
+
sh "yardoc"
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Runs the specs'
|
31
|
+
task :spec do
|
32
|
+
Dir['spec/**/*_spec.rb'].each { |f| sh "rspec #{f}" rescue nil }
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Runs the tests'
|
36
|
+
task :test => :spec
|
data/bin/casmall
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
require 'date'
|
5
|
+
require File.expand_path('version', File.dirname(__FILE__) + '/lib/casmall')
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'caruby-small'
|
9
|
+
s.summary = 'caSmall web service'
|
10
|
+
s.description = s.summary + '. See the Git README for more information.'
|
11
|
+
s.version = CaSmall::VERSION
|
12
|
+
s.date = Date.today
|
13
|
+
s.author = "OHSU"
|
14
|
+
s.email = "loneyf@ohsu.edu"
|
15
|
+
s.require_path = 'lib'
|
16
|
+
s.bindir = 'bin'
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files spec`.split("\n")
|
19
|
+
s.executables = `git ls-files bin`.split("\n").map { |f| File.basename(f) }
|
20
|
+
s.add_runtime_dependency 'bundler'
|
21
|
+
s.add_runtime_dependency 'rack'
|
22
|
+
s.add_runtime_dependency 'sinatra'
|
23
|
+
s.add_runtime_dependency 'sinatra-authorization'
|
24
|
+
s.add_runtime_dependency 'jruby-openssl'
|
25
|
+
s.add_runtime_dependency 'caruby-tissue', '>= 2.1.5'
|
26
|
+
s.add_development_dependency 'yard'
|
27
|
+
s.add_development_dependency 'rake'
|
28
|
+
s.has_rdoc = 'yard'
|
29
|
+
s.license = 'MIT'
|
30
|
+
end
|
data/config.ru
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.require
|
4
|
+
|
5
|
+
require 'casmall'
|
6
|
+
require 'jinx/helpers/log'
|
7
|
+
|
8
|
+
# the logger
|
9
|
+
use Rack::CommonLogger, Jinx.logger(:app => 'CaSmall', :debug => true)
|
10
|
+
|
11
|
+
# start the application
|
12
|
+
run CaSmall::App.new(CaTissue)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'sinatra/authorization'
|
2
|
+
|
3
|
+
module CaSmall
|
4
|
+
module Authorization
|
5
|
+
include Sinatra::Authorization
|
6
|
+
|
7
|
+
# Runs the given block in an HTTP basic authorization context.
|
8
|
+
# The session status is set to the result of performing the given block.
|
9
|
+
#
|
10
|
+
# @yield perform the caTissue operation and return a status message
|
11
|
+
def protect!(&block)
|
12
|
+
login_required
|
13
|
+
CaTissue::Database.current.open(session[:email], session[:password], &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [CaTissue::User] the user who is submitting this edit
|
17
|
+
# @raise [ArgumentError] if there is no such caTissue user
|
18
|
+
def current_user
|
19
|
+
# The caTissue login name is the user's email address.
|
20
|
+
email = session[:email]
|
21
|
+
raise ScatError.new("The caTissue login is not available in this web session.") unless email
|
22
|
+
# the current caTissue User
|
23
|
+
user = CaTissue::User.new(:email_address => email)
|
24
|
+
# the cached caTissue User id
|
25
|
+
user_id = session[:user_id]
|
26
|
+
if user_id then
|
27
|
+
user.identifier = user_id
|
28
|
+
else
|
29
|
+
# Fetch the User and cache the id.
|
30
|
+
raise ScatError.new("User not found: #{user.email_address}") unless user.find
|
31
|
+
session[:user_id] = user.identifier
|
32
|
+
end
|
33
|
+
user
|
34
|
+
end
|
35
|
+
|
36
|
+
# Fix +Sinatra::Authorization.authorization_realm+ per the
|
37
|
+
# (https://github.com/sr/sinatra-authorization)[https://github.com/sr/sinatra-authorization]
|
38
|
+
# patch.
|
39
|
+
def authorization_realm
|
40
|
+
settings.authorization_realm
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Obtains the HTML Basic authorization username and password.
|
46
|
+
# Formats the caTissue login name as _username_+@+_domain_,
|
47
|
+
# where _domain_ is the domain portion of the system +hostname+.
|
48
|
+
#
|
49
|
+
# @param [String] the caTissue login name, with or without the +@+_domain_ suffix
|
50
|
+
# @param [String] the caTissue password
|
51
|
+
# @return [Boolean] the authorization result
|
52
|
+
def authorize(username, password)
|
53
|
+
email = session[:email] = infer_email_address(username)
|
54
|
+
session[:password] = password
|
55
|
+
# Try to start a session.
|
56
|
+
begin
|
57
|
+
CaTissue::Database.current.open(email, password) {}
|
58
|
+
logger.debug { "Scat captured the caTissue login name #{email} and password." }
|
59
|
+
true
|
60
|
+
rescue Exception => e
|
61
|
+
logger.debug { "Scat caTissue login #{email.qp} with password #{password.qp} is invalid." }
|
62
|
+
session[:status] = "caTissue login was unsuccessful - #{e.message}"
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [String] the username, with or without the +@+_domain_ suffix
|
68
|
+
# @param [String] the email address
|
69
|
+
def infer_email_address(username)
|
70
|
+
if username.index('@') then
|
71
|
+
username
|
72
|
+
else
|
73
|
+
# The email domain is the last two components of the hostname, e.g.
|
74
|
+
# the prod01.cluster.galena.edu domain is galena.edu.
|
75
|
+
domain = `hostname`.chomp[/[^.]+\.[^.]+$/]
|
76
|
+
domain.empty? ? username : [username, domain].join('@')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module CaSmall
|
4
|
+
# The WebService processes catissuews requests.
|
5
|
+
class WebService
|
6
|
+
# @param [Module] mod the application domain module, e.g. +CaTissue+.
|
7
|
+
def initialize(mod)
|
8
|
+
@context = mod
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [String] name the search target class name, singular or plural
|
12
|
+
# @param [{String=>String}] params the attribute => value search arguments
|
13
|
+
# @return [String, nil] the JSON content of the matching object(s), or nil if no match
|
14
|
+
def find(name, params)
|
15
|
+
# the caTissue class to find
|
16
|
+
tgt = name.singularize
|
17
|
+
logger.info { "caSmall finding #{name.qp} #{params.qp}..." }
|
18
|
+
klass = @context.const_get(tgt.camelize)
|
19
|
+
# the attribute => value hash
|
20
|
+
vh = {}
|
21
|
+
# Convert the parameters into attribute => value entries.
|
22
|
+
params.each do |k, v|
|
23
|
+
pa = k.to_sym
|
24
|
+
# the standard property
|
25
|
+
prop = klass.property(pa)
|
26
|
+
# Convert a numeric attribute string argument to an integer.
|
27
|
+
v = v.to_i if prop.type < Java::JavaLang::Number
|
28
|
+
vh[pa] = v
|
29
|
+
end
|
30
|
+
# the search template
|
31
|
+
tmpl = klass.new(vh)
|
32
|
+
# the search result
|
33
|
+
result = tgt == name ? tmpl.find : tmpl.query
|
34
|
+
# convert the search result, if any, to JSON
|
35
|
+
if result then
|
36
|
+
logger.info { "caSmall found #{result.qp}." }
|
37
|
+
result.to_json
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String] json the JSON representation of the query template
|
42
|
+
# @param [String, nil] path the optional query attribute path
|
43
|
+
# @return [String, nil] the JSON content of the matching objects, or nil if no match
|
44
|
+
def query(json, path=nil)
|
45
|
+
path_a = path ? path.split('/').map { |s| s.to_sym } : Array::EMPTY_ARRAY
|
46
|
+
# Bump the default nesting, since a query result can be deeply nested.
|
47
|
+
JSON[json].query(*path_a).to_json(:max_nesting => 100)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param [String] json the JSON representation of the object to create
|
51
|
+
# @return [String] the created object's identifier as a JSON string
|
52
|
+
def create(json)
|
53
|
+
JSON[json].create.identifier.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param [String] json the JSON representation of the object to update
|
57
|
+
def update(json)
|
58
|
+
obj = JSON[json]
|
59
|
+
if obj.identifier.nil? then
|
60
|
+
obj.find or raise NotFoundError.new("Object to update was not found in the database: #{obj}")
|
61
|
+
end
|
62
|
+
obj.update
|
63
|
+
true.to_json
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/casmall.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'catissue'
|
3
|
+
require 'casmall/authorization'
|
4
|
+
require 'casmall/web_service'
|
5
|
+
|
6
|
+
module CaSmall
|
7
|
+
class App < Sinatra::Base
|
8
|
+
include Authorization
|
9
|
+
|
10
|
+
set :root, File.dirname(__FILE__) + '/..'
|
11
|
+
|
12
|
+
if development? then
|
13
|
+
# Don't generate fancy HTML for stack traces.
|
14
|
+
disable :show_exceptions
|
15
|
+
# Allow errors to get out of the app so Cucumber can display them.
|
16
|
+
enable :raise_errors
|
17
|
+
end
|
18
|
+
|
19
|
+
# The authorization page name.
|
20
|
+
set :authorization_realm, 'Please enter your username and caTissue password'
|
21
|
+
|
22
|
+
enable :sessions
|
23
|
+
|
24
|
+
def initialize(mod, *args)
|
25
|
+
super(*args)
|
26
|
+
#the request handler.
|
27
|
+
@ws = CaSmall::WebService.new(mod)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Match on the class/id or class?attribute=value[&attribute=value ...].
|
31
|
+
get %r{/(\w+)(?:/(\d+))?} do |name, id|
|
32
|
+
# The value hash is either the id argument or the URL parameters.
|
33
|
+
vh = id ? {'identifier' => id} : params.delete_if { |k, v| k == 'captures' }
|
34
|
+
# delegate to the web service
|
35
|
+
@ws.find(name, vh)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Match on +query+ with request parameters.
|
39
|
+
post %r{/query(?:/([\w/]+))?} do |path|
|
40
|
+
@ws.query(params[:json], path)
|
41
|
+
end
|
42
|
+
|
43
|
+
post '/' do
|
44
|
+
@ws.create(params[:json])
|
45
|
+
end
|
46
|
+
|
47
|
+
put '/' do
|
48
|
+
@ws.update(params[:json])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/spec/create_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
module CaSmall
|
4
|
+
describe 'Create' do
|
5
|
+
include RackTest
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
@reg = seed.registration
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { @reg }
|
12
|
+
|
13
|
+
it 'should create a new registration' do
|
14
|
+
post '/', :json => subject.to_json
|
15
|
+
last_response.should be_ok
|
16
|
+
id_s = last_response.body
|
17
|
+
id_s.should match /^\d+$/
|
18
|
+
fetched = subject.class.new(:identifier => id_s.to_i).find
|
19
|
+
fetched.should_not be nil
|
20
|
+
scgs = fetched.specimen_collection_groups
|
21
|
+
scgs.size.should be 1
|
22
|
+
scgs.first.specimens.size.should be 1
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should create an annotation' do
|
26
|
+
pnt = @reg.participant
|
27
|
+
lab = CaTissue::Participant::Clinical::LabAnnotation.new
|
28
|
+
lab.merge_attributes(:lab_test_name => 'Test Lab', :participant => pnt)
|
29
|
+
post '/', :json => lab.to_json
|
30
|
+
last_response.should be_ok
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/find_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'spec/spec_helper'
|
3
|
+
|
4
|
+
module CaSmall
|
5
|
+
describe 'Find' do
|
6
|
+
include RackTest
|
7
|
+
|
8
|
+
it "should find an existing Site by name" do
|
9
|
+
site = CaTissue::Site.default_site
|
10
|
+
get "/site?name=#{URI.escape(site.name)}"
|
11
|
+
last_response.should be_ok
|
12
|
+
fetched = JSON[last_response.body]
|
13
|
+
fetched.identifier.should_not be_nil
|
14
|
+
site.content_matches?(fetched).should be true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should find an existing Participant" do
|
18
|
+
pnt = CaTissue::Participant.new(:last_name => Jinx::UID.generate.to_s).create
|
19
|
+
get "/participant/#{pnt.id}"
|
20
|
+
last_response.should be_ok
|
21
|
+
fetched = JSON[last_response.body]
|
22
|
+
fetched.identifier.should_not be_nil
|
23
|
+
pnt.content_matches?(fetched).should be true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/query_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
module CaSmall
|
4
|
+
describe 'Query' do
|
5
|
+
include RackTest
|
6
|
+
|
7
|
+
it 'should query an existing Site' do
|
8
|
+
site = CaTissue::Site.default_site
|
9
|
+
post "/query", :json => site.to_json
|
10
|
+
last_response.should be_ok
|
11
|
+
fetched = JSON[last_response.body]
|
12
|
+
fetched.size.should be 1
|
13
|
+
site.content_matches?(fetched.first).should be true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should query a Site -> coordinator path' do
|
17
|
+
site = CaTissue::Site.default_site
|
18
|
+
post '/query/coordinator', :json => site.to_json
|
19
|
+
last_response.should be_ok
|
20
|
+
fetched = JSON[last_response.body]
|
21
|
+
fetched.size.should be 1
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should query registration specimens' do
|
25
|
+
reg = seed.registration.create
|
26
|
+
pnt = reg.participant
|
27
|
+
spc = pnt.specimens.first
|
28
|
+
tmpl = reg.copy(:identifier)
|
29
|
+
post '/query/specimen_collection_groups/specimens', :json => tmpl.to_json
|
30
|
+
last_response.should be_ok
|
31
|
+
fetched = JSON[last_response.body]
|
32
|
+
fetched.size.should be 1
|
33
|
+
fetched.first.content_matches?(spc).should be true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.require(:test, :development)
|
4
|
+
|
5
|
+
require 'casmall'
|
6
|
+
|
7
|
+
module CaSmall::Test
|
8
|
+
RESULTS = File.dirname(__FILE__) + '/../test/results'
|
9
|
+
end
|
10
|
+
|
11
|
+
# Open the logger.
|
12
|
+
Jinx::Log.instance.open(CaSmall::Test::RESULTS + '/log/casmall.log', :debug => true)
|
13
|
+
|
14
|
+
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require Bundler.environment.specs.detect { |s| s.name == 'caruby-tissue' }.full_gem_path + '/test/helpers/seed'
|
3
|
+
|
4
|
+
def app
|
5
|
+
CaSmall::App.new(CaTissue)
|
6
|
+
end
|
7
|
+
|
8
|
+
module CaSmall
|
9
|
+
module RackTest
|
10
|
+
include Rack::Test::Methods
|
11
|
+
|
12
|
+
def seed
|
13
|
+
CaTissue::TestCase::Seed.new.uniquify
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/update_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
module CaSmall
|
4
|
+
describe 'Update' do
|
5
|
+
include RackTest
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
@spc = seed.specimen.create
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { @spc }
|
12
|
+
|
13
|
+
it 'should update a specimen quantity' do
|
14
|
+
qty = subject.available_quantity /= 2
|
15
|
+
put '/', :json => subject.to_json
|
16
|
+
last_response.should be_ok
|
17
|
+
fetched = subject.copy(:identifier).find
|
18
|
+
fetched.available_quantity.should be_within(0.00001).of(qty)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should add a specimen annotation' do
|
22
|
+
pst = CaTissue::Specimen::Pathology::ProstateSpecimenPathologyAnnotation.new
|
23
|
+
pst.merge_attributes(:specimen => subject)
|
24
|
+
grd = CaTissue::Specimen::Pathology::SpecimenHistologicGrade.new
|
25
|
+
grd.merge_attributes(:grade => 3, :specimen_base_solid_tissue_pathology_annotation => pst)
|
26
|
+
put '/', :json => subject.to_json
|
27
|
+
last_response.should be_ok
|
28
|
+
# TODO - Uncomment when annotation query supported
|
29
|
+
# fetched = subject.copy(:identifier).find
|
30
|
+
# fpst = fetched.pathology.prostate_specimen_pathology_annotations.first
|
31
|
+
# fpst.should_not be nil
|
32
|
+
# fgrd = fpst.histologic_grades.first
|
33
|
+
# fgrd.should_not be nil
|
34
|
+
# fgrd.grade.should be grd.grade
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: caruby-small
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 1.1.2
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- OHSU
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-07-17 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bundler
|
17
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
requirement: *id001
|
24
|
+
prerelease: false
|
25
|
+
type: :runtime
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rack
|
28
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
requirement: *id002
|
35
|
+
prerelease: false
|
36
|
+
type: :runtime
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: sinatra
|
39
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
requirement: *id003
|
46
|
+
prerelease: false
|
47
|
+
type: :runtime
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: sinatra-authorization
|
50
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
requirement: *id004
|
57
|
+
prerelease: false
|
58
|
+
type: :runtime
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: jruby-openssl
|
61
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
requirement: *id005
|
68
|
+
prerelease: false
|
69
|
+
type: :runtime
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: caruby-tissue
|
72
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.1.5
|
78
|
+
requirement: *id006
|
79
|
+
prerelease: false
|
80
|
+
type: :runtime
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: yard
|
83
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
requirement: *id007
|
90
|
+
prerelease: false
|
91
|
+
type: :development
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: rake
|
94
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
requirement: *id008
|
101
|
+
prerelease: false
|
102
|
+
type: :development
|
103
|
+
description: caSmall web service. See the Git README for more information.
|
104
|
+
email: loneyf@ohsu.edu
|
105
|
+
executables:
|
106
|
+
- casmall
|
107
|
+
extensions: []
|
108
|
+
|
109
|
+
extra_rdoc_files: []
|
110
|
+
|
111
|
+
files:
|
112
|
+
- .gitignore
|
113
|
+
- Gemfile
|
114
|
+
- Gemfile.lock
|
115
|
+
- History.md
|
116
|
+
- LEGAL
|
117
|
+
- LICENSE
|
118
|
+
- README.md
|
119
|
+
- Rakefile
|
120
|
+
- bin/casmall
|
121
|
+
- caruby-small.gemspec
|
122
|
+
- config.ru
|
123
|
+
- lib/casmall.rb
|
124
|
+
- lib/casmall/authorization.rb
|
125
|
+
- lib/casmall/version.rb
|
126
|
+
- lib/casmall/web_service.rb
|
127
|
+
- spec/create_spec.rb
|
128
|
+
- spec/find_spec.rb
|
129
|
+
- spec/query_spec.rb
|
130
|
+
- spec/spec_helper.rb
|
131
|
+
- spec/support/rack_test.rb
|
132
|
+
- spec/update_spec.rb
|
133
|
+
homepage:
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: "0"
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: "0"
|
153
|
+
requirements: []
|
154
|
+
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 1.8.15
|
157
|
+
signing_key:
|
158
|
+
specification_version: 3
|
159
|
+
summary: caSmall web service
|
160
|
+
test_files:
|
161
|
+
- spec/create_spec.rb
|
162
|
+
- spec/find_spec.rb
|
163
|
+
- spec/query_spec.rb
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/support/rack_test.rb
|
166
|
+
- spec/update_spec.rb
|
167
|
+
has_rdoc: yard
|