genevalidatorapp 1.4.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +4 -0
  5. data/GeneValidatorApp.gemspec +50 -0
  6. data/LICENSE.txt +661 -0
  7. data/README.md +101 -0
  8. data/Rakefile +14 -0
  9. data/bin/genevalidatorapp +122 -0
  10. data/config.ru +3 -0
  11. data/lib/GeneValidatorApp.rb +321 -0
  12. data/lib/GeneValidatorApp/config.rb +86 -0
  13. data/lib/GeneValidatorApp/database.rb +114 -0
  14. data/lib/GeneValidatorApp/genevalidator.rb +241 -0
  15. data/lib/GeneValidatorApp/logger.rb +24 -0
  16. data/lib/GeneValidatorApp/version.rb +3 -0
  17. data/public/GeneValidator/.gitkeep +0 -0
  18. data/public/web_files/css/bootstrap.min.css +7 -0
  19. data/public/web_files/css/bootstrap1.min.css +7 -0
  20. data/public/web_files/css/custom.css +521 -0
  21. data/public/web_files/css/custom.min.css +3 -0
  22. data/public/web_files/css/font-awesome.min.css +4 -0
  23. data/public/web_files/fonts/FontAwesome.otf +0 -0
  24. data/public/web_files/fonts/fontawesome-webfont.eot +0 -0
  25. data/public/web_files/fonts/fontawesome-webfont.svg +504 -0
  26. data/public/web_files/fonts/fontawesome-webfont.ttf +0 -0
  27. data/public/web_files/fonts/fontawesome-webfont.woff +0 -0
  28. data/public/web_files/img/gene.png +0 -0
  29. data/public/web_files/js/bionode-seq.min.js +1 -0
  30. data/public/web_files/js/bootstrap.min.js +6 -0
  31. data/public/web_files/js/d3.v3.min.js +5 -0
  32. data/public/web_files/js/genevalidator.js +282 -0
  33. data/public/web_files/js/genevalidator.min.js +1 -0
  34. data/public/web_files/js/jquery.cookie.min.js +1 -0
  35. data/public/web_files/js/jquery.min.js +4 -0
  36. data/public/web_files/js/jquery.tablesorter.min.js +5 -0
  37. data/public/web_files/js/jquery.validate.min.js +4 -0
  38. data/public/web_files/js/plots.js +744 -0
  39. data/public/web_files/js/plots.min.js +1 -0
  40. data/spec/app_spec.rb +107 -0
  41. data/spec/database/funky_ids/funky_ids.fa +10 -0
  42. data/spec/database/funky_ids/funky_ids.fa.nhr +0 -0
  43. data/spec/database/funky_ids/funky_ids.fa.nin +0 -0
  44. data/spec/database/funky_ids/funky_ids.fa.nog +0 -0
  45. data/spec/database/funky_ids/funky_ids.fa.nsd +9 -0
  46. data/spec/database/funky_ids/funky_ids.fa.nsi +0 -0
  47. data/spec/database/funky_ids/funky_ids.fa.nsq +0 -0
  48. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta +6449 -0
  49. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.phr +0 -0
  50. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pin +0 -0
  51. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.pog +0 -0
  52. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.psd +2378 -0
  53. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.psi +0 -0
  54. data/spec/database/sample/proteins/Solenopsis_invicta/Sinvicta2-2-3.prot.subset.fasta.psq +0 -0
  55. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta +5486 -0
  56. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nhr +0 -0
  57. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nin +0 -0
  58. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nog +0 -0
  59. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsd +946 -0
  60. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsi +0 -0
  61. data/spec/database/sample/transcripts/Solenopsis_invicta/Sinvicta2-2-3.cdna.subset.fasta.nsq +0 -0
  62. data/spec/database/unformatted/Cardiocondyla_obscurior/Cobs1.4.proteins.fa +148303 -0
  63. data/spec/database/without_parse_seqids/without_parse_seqids.fa +10 -0
  64. data/spec/database/without_parse_seqids/without_parse_seqids.fa.phr +0 -0
  65. data/spec/database/without_parse_seqids/without_parse_seqids.fa.pin +0 -0
  66. data/spec/database/without_parse_seqids/without_parse_seqids.fa.psq +0 -0
  67. data/spec/database_spec.rb +37 -0
  68. data/spec/empty_config.yml +0 -0
  69. data/views/500.slim +5 -0
  70. data/views/index.slim +66 -0
  71. data/views/layout.slim +85 -0
  72. metadata +337 -0
@@ -0,0 +1,101 @@
1
+ # GeneValidatorApp
2
+ [![Build Status](https://travis-ci.org/wurmlab/GeneValidatorApp.svg?branch=master)](https://travis-ci.org/wurmlab/GeneValidatorApp)
3
+ [![Gem Version](https://badge.fury.io/rb/GeneValidatorApp.svg)](http://badge.fury.io/rb/GeneValidatorApp)
4
+ [![Dependency Status](https://gemnasium.com/wurmlab/GeneValidatorApp.svg)](https://gemnasium.com/wurmlab/GeneValidatorApp)
5
+ [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wurmlab/GeneValidatorApp/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wurmlab/GeneValidatorApp/?branch=master)
6
+
7
+ This is a Sinatra based web wrapper for [GeneValidator](https://github.com/monicadragan/GeneValidator); a program that validates gene predictions. A working example can be seen at [genevalidator.sbcs.qmul.ac.uk](http://genevalidator.sbcs.qmul.ac.uk).
8
+
9
+ If you use this program in your research, please cite us as follows:
10
+
11
+ "Dragan M, Moghul MI, Priyam A & Wurm Y (<em>in prep</em>) GeneValidator: identify problematic gene predictions"
12
+
13
+ This program was developed at [Wurm Lab](http://yannick.poulet.org), [QMUL](http://sbcs.qmul.ac.uk) with the support of a BBSRC grant.
14
+
15
+ ## Installation
16
+
17
+ 1) Install all GeneValidator Prerequisites (ruby <=1.9.3, Mafft, BLAST+, GSL). You would also require a BLAST database.
18
+ * Please see [here](https://gist.github.com/IsmailM/b783e8a06565197084e6) for more information.
19
+
20
+ 2) Install GeneValidatorApp
21
+
22
+ $ gem install genevalidatorapp
23
+
24
+ ## Usage
25
+
26
+ After installing simply type in:
27
+
28
+ $ genevalidatorapp
29
+
30
+ and then go to [http://localhost:4567](http://localhost:4567) (if on a local server and using the default port: 4567)
31
+
32
+ See `$ genevalidator -h` for more information on how to run GeneValidatorApp.
33
+
34
+ USAGE
35
+
36
+ genevalidatorapp [options]
37
+
38
+ Example
39
+
40
+ # Launch GeneValidatorApp with the given config file
41
+ $ genevalidatorapp --config ~/.genevalidatorapp.conf
42
+
43
+ # Launch GeneValidatorApp with 8 threads at port 8888
44
+ $ genevalidatorapp --num_threads 8 --port 8888
45
+
46
+ # Create a config file with the other arguments
47
+ $ genevalidatorapp -s -d ~/database_dir
48
+
49
+ Compulsory (unless set in a config file)
50
+ -d, --database_dir Read BLAST database from this directory
51
+
52
+ Optional
53
+ -f, --default_db The Path to the the default database
54
+ -n, --num_threads Number of threads to use to run a BLAST search
55
+ -c, --config_file Use the given configuration file
56
+ -r, --require Load extension from this file
57
+ -p, --port Port to run GeneValidatorApp on
58
+ -s, --set Set configuration value in default or given config file
59
+ -l, --list_databases List BLAST databases
60
+ -b, --blast_bin Load BLAST+ binaries from this directory
61
+ -m, --mafft_bin Load Mafft binaries from this directory
62
+ -D, --devel Start GeneValidatorApp in development mode
63
+ -v, --version Print version number of GeneValidatorApp that will be loaded
64
+ -h, --help Display this help message.
65
+
66
+
67
+ ## Setting up a Config File
68
+
69
+ GeneValidatorApp requires a number of arguments in order to work. You can either provide these variables to the app through a config file or through command line arguments.
70
+
71
+ In order to create a config file, run genevalidator with the `-s` or `--set` argument as follows.
72
+
73
+ $ genevalidator -s -d database_dir -f default_db -n num_threads -p port -b blast_bin -m mafft_bin
74
+
75
+ The `--set` argument create a config file at `~/.genevalidatorapp.conf` using all the other arguments used. Thereafter, GeneValidatorApp will read the config file before starting the app. This means that you are not required provide the same arguments again and again.
76
+
77
+ ### Config file
78
+
79
+ A config file can also be set up manually. Below is an example:
80
+
81
+ :database_dir: "/Users/ismailm/blastdb"
82
+ :default_db: "/Users/ismailm/blastdb/SwissProt"
83
+ :web_dir: "/Users/ismailm/GV"
84
+ :num_threads: 8
85
+ :port: 4567
86
+ :host: localhost
87
+ :devel: true
88
+ :blast_bin: "/Users/ismailm/blast/bin"
89
+ :mafft_bin: "/Users/ismailm/mafft/bin"
90
+
91
+ ## API
92
+
93
+ See [GeneValidatorApp-API](https://github.com/IsmailM/GeneValidatorApp-API) for more information.
94
+
95
+ ## Contributing
96
+
97
+ 1. Fork it ( https://github.com/wurmlab/GeneValidatorApp/fork )
98
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
99
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
100
+ 4. Push to the branch (`git push origin my-new-feature`)
101
+ 5. Create a new Pull Request
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core'
3
+ require 'rspec/core/rake_task'
4
+
5
+ task default: [:build]
6
+ desc 'Installs the ruby gem'
7
+ task :build do
8
+ exec("gem build GeneValidatorApp.gemspec && gem install ./GeneValidatorApp-#{GeneValidatorApp::VERSION}.gem")
9
+ end
10
+
11
+ task test: :spec
12
+ RSpec::Core::RakeTask.new(:spec) do |spec|
13
+ spec.pattern = FileList['spec/**/*_spec.rb']
14
+ end
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+ require 'slop'
3
+
4
+ ENV['RACK_ENV'] ||= 'production'
5
+
6
+ # display name for tools like `ps`
7
+ $PROGRAM_NAME = 'genevalidatorapp'
8
+
9
+ opts = Slop.parse do |o|
10
+ o.banner = <<BNR
11
+
12
+ SUMMARY:
13
+ GeneValidator - Identify problems with predicted genes
14
+
15
+ USAGE:
16
+ $ genevalidatorapp [options]
17
+
18
+ Examples:
19
+ # Launch GeneValidatorApp with the given config file
20
+ $ genevalidatorapp --config ~/.genevalidatorapp.conf
21
+
22
+ # Launch GeneValidatorApp with 8 threads at port 8888
23
+ $ genevalidatorapp --num_threads 8 --port 8888
24
+
25
+ # Create a config file with the other arguments
26
+ $ genevalidatorapp -s -d ~/database_dir
27
+ BNR
28
+
29
+ o.separator 'Compulsory Argument, unless set in a config file'
30
+
31
+ o.string '-d', '--database_dir',
32
+ 'Read BLAST database from this directory'
33
+
34
+ o.separator ''
35
+ o.separator 'Optional Arguments'
36
+
37
+ o.string '-f', '--default_db',
38
+ 'The Path to the the default database'
39
+
40
+ o.string '-n', '--num_threads',
41
+ 'Number of threads to use to run a BLAST search'
42
+
43
+ o.string '-c', '--config_file',
44
+ 'Use the given configuration file'
45
+
46
+ o.string '-r', '--require',
47
+ 'Load extension from this file'
48
+
49
+ o.string '--host',
50
+ 'Host to run GeneValidatorApp on'
51
+
52
+ o.string '-p', '--port',
53
+ 'Port to run GeneValidatorApp on'
54
+
55
+ o.string '-s', '--set',
56
+ 'Set configuration value in the config file'
57
+
58
+ o.string '-l', '--list_dbs',
59
+ 'List BLAST databases'
60
+
61
+ o.string '-b', '--blast_bin',
62
+ 'Load BLAST+ binaries from this directory'
63
+
64
+ o.string '-m', '--mafft_bin',
65
+ 'Load Mafft binaries from this directory'
66
+
67
+ o.string '-w', '--web_dir',
68
+ 'Path to the web directory (contains ' \
69
+ 'supporting files utilised by the app).'
70
+
71
+ o.bool '-D', '--devel',
72
+ 'Start GeneValidatorApp in development mode'
73
+
74
+ o.bool '-v', '--version',
75
+ 'Print version number of GeneValidatorApp that will be loaded'
76
+
77
+ o.on '-h', '--help',
78
+ 'Display this help message'
79
+ end
80
+
81
+ if opts.help?
82
+ puts opts
83
+ exit
84
+ end
85
+
86
+ if opts.version?
87
+ require 'GeneValidatorApp/version'
88
+ puts GeneValidatorApp::VERSION
89
+ exit
90
+ end
91
+
92
+ ENV['RACK_ENV'] = 'development' if opts.devel?
93
+
94
+ # Exit gracefully on SIGINT.
95
+ stty = `stty -g`.chomp
96
+ trap('INT') do
97
+ puts ''
98
+ puts 'Aborted.'
99
+ system('stty', stty)
100
+ exit
101
+ end
102
+
103
+ clean_opts = lambda do |hash|
104
+ hash.delete_if { |k, v| k == :set || k == :version || v.nil? }
105
+ hash
106
+ end
107
+
108
+ require 'GeneValidatorApp'
109
+ begin
110
+ GeneValidatorApp.init clean_opts[opts.to_hash]
111
+ rescue SystemExit => e
112
+ puts '*** Error: GeneValidator failed to initialise properly.'
113
+ puts ' Please check all paramaters and try again.'
114
+ puts ' See https://github.com/IsmailM/GeneValidatorApp for more help'
115
+ exit e.status
116
+ end
117
+
118
+ puts GeneValidatorApp::Database.all? if opts.list_databases?
119
+
120
+ GeneValidatorApp.send(:write_config_file) if opts.set?
121
+
122
+ GeneValidatorApp.run
@@ -0,0 +1,3 @@
1
+ require 'GeneValidatorApp'
2
+ GeneValidatorApp.init
3
+ run GeneValidatorApp
@@ -0,0 +1,321 @@
1
+ require 'GeneValidatorApp/database'
2
+ require 'GeneValidatorApp/genevalidator'
3
+ require 'GeneValidatorApp/logger'
4
+ require 'GeneValidatorApp/config'
5
+ require 'GeneValidatorApp/version'
6
+ require 'genevalidator/version'
7
+
8
+ require 'pathname'
9
+ require 'yaml'
10
+ require 'sinatra/base'
11
+ require 'sinatra/cross_origin'
12
+ require 'slim'
13
+ require 'thin'
14
+
15
+ module GeneValidatorApp
16
+ # Use a fixed minimum version of BLAST+
17
+ MINIMUM_BLAST_VERSION = '2.2.30+'
18
+
19
+ class << self
20
+ attr_reader :public_dir, :tempdir, :config
21
+
22
+ # Returns the Rack Environment
23
+ def environment
24
+ ENV['RACK_ENV']
25
+ end
26
+
27
+ # Run by the logger method - sets the logger level to verbose if in
28
+ # development environment
29
+ def verbose?
30
+ @verbose ||= (environment == 'development')
31
+ end
32
+
33
+ # Root dir of the App
34
+ def root
35
+ Pathname.new(__FILE__).dirname.parent
36
+ end
37
+
38
+ def logger
39
+ @logger ||= Logger.new(STDERR, verbose?)
40
+ end
41
+
42
+ # Setting up the environment before running the app...
43
+ def init(config = {})
44
+ @config = Config.new(config)
45
+ init_blast_and_mafft_binaries
46
+ init_database
47
+ load_extension
48
+ check_num_threads
49
+ check_max_characters
50
+ init_gv_tempdir
51
+ init_public_dir
52
+ self
53
+ end
54
+
55
+ # Starting the app manually using Thin
56
+ def run
57
+ check_host
58
+ url = "http://#{config[:host]}:#{config[:port]}"
59
+ server = Thin::Server.new(config[:host], config[:port], signals: false) do
60
+ use Rack::CommonLogger if GeneValidatorApp.environment == 'development'
61
+ run GeneValidatorApp
62
+ end
63
+ server.timeout = 2700 # 45 minutes
64
+ server.silent = true
65
+ server.backend.start do
66
+ puts '** GeneValidatorApp is ready.'
67
+ puts " Go to #{url} in your browser and start analysing Genes!"
68
+ puts ' Press CTRL+C to quit.'
69
+ puts
70
+ open_default_browser(url)
71
+ [:INT, :TERM].each do |sig|
72
+ trap sig do
73
+ server.stop!
74
+ puts
75
+ puts
76
+ puts '** Thank you for using GeneValidatorApp :).'
77
+ puts ' Please cite: '
78
+ puts ' Dragan M., Moghul M.I., Priyam A., Wurm Y (in prep).'
79
+ puts ' GeneValidator: identify problematic gene predictions.'
80
+ end
81
+ end
82
+ end
83
+ rescue
84
+ puts '** Oops! There was an error.'
85
+ puts " Is GeneValidatorApp already accessible at #{url}?"
86
+ puts ' Try running GeneValidatorApp on another port, like so:'
87
+ puts
88
+ puts ' genevalidatorapp -p 4570.'
89
+ end
90
+
91
+ # Set the max characters accepted from the app (for the app templates)
92
+ def max_characters
93
+ (config[:max_characters]) ? config[:max_characters] : 'undefined'
94
+ end
95
+
96
+ def [](key)
97
+ config[key]
98
+ end
99
+
100
+ # Rack-interface.
101
+ #
102
+ # Inject our logger in the env and dispatch request to our
103
+ # controller.
104
+ def call(env)
105
+ env['rack.logger'] = logger
106
+ App.call(env)
107
+ end
108
+
109
+ private
110
+
111
+ def open_default_browser(url)
112
+ return if using_ssh?
113
+ if RUBY_PLATFORM =~ /linux/
114
+ `xdg-open #{url}` unless command?('xdg-open') || ENV['DISPLAY']
115
+ elsif RUBY_PLATFORM =~ /darwin/
116
+ `open #{url}`
117
+ end
118
+ end
119
+
120
+ def using_ssh?
121
+ true if ENV['SSH_CLIENT'] || ENV['SSH_TTY'] || ENV['SSH_CONNECTION']
122
+ end
123
+
124
+ def init_blast_and_mafft_binaries
125
+ init_binaries(config[:blast_bin], 'NCBI BLAST+')
126
+ assert_blast_installed_and_compatible
127
+ init_binaries(config[:mafft_bin], 'Mafft')
128
+ assert_mafft_installed
129
+ end
130
+
131
+ def init_binaries(bin_dir, type)
132
+ if bin_dir
133
+ bin_dir = File.expand_path bin_dir
134
+ unless File.exist?(bin_dir) && File.directory?(bin_dir)
135
+ fail BIN_DIR_NOT_FOUND, bin_dir
136
+ end
137
+ logger.debug("Will use #{type} at: #{config[:blast_bin]}")
138
+ export_bin_dir bin_dir
139
+ else
140
+ logger.debug("Will use #{type} at: $PATH")
141
+ end
142
+ end
143
+
144
+ def init_database
145
+ fail DATABASE_DIR_NOT_SET unless config[:database_dir]
146
+
147
+ config[:database_dir] = File.expand_path(config[:database_dir])
148
+ unless File.exist?(config[:database_dir]) &&
149
+ File.directory?(config[:database_dir])
150
+ fail DATABASE_DIR_NOT_FOUND, config[:database_dir]
151
+ end
152
+
153
+ assert_blast_databases_present_in_database_dir
154
+ logger.debug("Will use BLAST+ databases at: #{config[:database_dir]}")
155
+
156
+ Database.scan_databases_dir
157
+ Database.each do |database|
158
+ logger.debug("Found #{database.type.chomp} database" \
159
+ " '#{database.title.chomp}' at '#{database.name.chomp}'")
160
+ end
161
+ end
162
+
163
+ def check_num_threads
164
+ num_threads = Integer(config[:num_threads])
165
+ fail NUM_THREADS_INCORRECT unless num_threads > 0
166
+ logger.debug "Will use #{num_threads} threads to run BLAST."
167
+ if num_threads > 256
168
+ logger.warn "Number of threads set at #{num_threads} is unusually high."
169
+ end
170
+ rescue
171
+ raise NUM_THREADS_INCORRECT
172
+ end
173
+
174
+ def check_max_characters
175
+ Integer(config[:max_characters]) if config[:max_characters]
176
+ rescue
177
+ raise MAX_CHARACTERS_INCORRECT
178
+ end
179
+
180
+ def load_extension
181
+ return unless config[:require]
182
+
183
+ config[:require] = File.expand_path config[:require]
184
+ unless File.exist?(config[:require]) && File.file?(config[:require])
185
+ fail EXTENSION_FILE_NOT_FOUND, config[:require]
186
+ end
187
+
188
+ logger.debug("Loading extension: #{config[:require]}")
189
+ require config[:require]
190
+ end
191
+
192
+ # Asserts whether mafft is installed.
193
+ def assert_mafft_installed
194
+ fail MAFFT_NOT_INSTALLED unless command? 'mafft'
195
+ end
196
+
197
+ def assert_blast_installed_and_compatible
198
+ fail BLAST_NOT_INSTALLED unless command? 'blastdbcmd'
199
+ version = `blastdbcmd -version`.split[1]
200
+ fail BLAST_NOT_COMPATIBLE, version unless version >= MINIMUM_BLAST_VERSION
201
+ end
202
+
203
+ def assert_blast_databases_present_in_database_dir
204
+ cmd = "blastdbcmd -recursive -list #{config[:database_dir]}"
205
+ out = `#{cmd}`
206
+ errpat = /BLAST Database error/
207
+ fail NO_BLAST_DATABASE_FOUND, config[:database_dir] if out.empty?
208
+ fail BLAST_DATABASE_ERROR, cmd, out if out.match(errpat) ||
209
+ !$?.success?
210
+ end
211
+
212
+ # Export bin dir to PATH environment variable.
213
+ def export_bin_dir(bin_dir)
214
+ return unless bin_dir
215
+ return if ENV['PATH'].split(':').include? bin_dir
216
+ ENV['PATH'] = "#{bin_dir}:#{ENV['PATH']}"
217
+ end
218
+
219
+ # Creates a Temp directory (starting with 'GeneValidator_') each time
220
+ # GVapp is started. Within this Temp folder, sub directories are created
221
+ # in which GeneValidator is run.
222
+ def init_gv_tempdir
223
+ @tempdir = Pathname.new(Dir.mktmpdir('GeneValidator_'))
224
+ end
225
+
226
+ # Copy the public folder (in the app root) to the web_dir location - this
227
+ # web_dir is then used by the app to serve all dependencies...
228
+ def init_public_dir
229
+ @public_dir = Pathname.new(config[:web_dir]) +
230
+ "GeneValidator_#{Time.now.strftime('%Y%m%d-%H%M%S')}"
231
+ root_public_dir = GeneValidatorApp.root + 'public'
232
+ FileUtils.cp_r(root_public_dir, @public_dir)
233
+ end
234
+
235
+ # Check and warn user if host is 0.0.0.0 (default).
236
+ def check_host
237
+ if config[:host] == '0.0.0.0'
238
+ logger.warn 'Will listen on all interfaces (0.0.0.0).' \
239
+ ' Consider using 127.0.0.1 (--host option).'
240
+ end
241
+ end
242
+
243
+ # Return `true` if the given command exists and is executable.
244
+ def command?(command)
245
+ system("which #{command} > /dev/null 2>&1")
246
+ end
247
+ end
248
+
249
+ # The Actual App...
250
+ class App < Sinatra::Base
251
+ register Sinatra::CrossOrigin
252
+
253
+ configure do
254
+ # We don't need Rack::MethodOverride. Let's avoid the overhead.
255
+ disable :method_override
256
+
257
+ # Ensure exceptions never leak out of the app. Exceptions raised within
258
+ # the app must be handled by the app. We do this by attaching error
259
+ # blocks to exceptions we know how to handle and attaching to Exception
260
+ # as fallback.
261
+ disable :show_exceptions, :raise_errors
262
+
263
+ # Make it a policy to dump to 'rack.errors' any exception raised by the
264
+ # app so that error handlers don't have to do it themselves. But for it
265
+ # to always work, Exceptions defined by us should not respond to `code`
266
+ # or http_status` methods. Error blocks errors must explicitly set http
267
+ # status, if needed, by calling `status` method.
268
+ enable :dump_errors
269
+
270
+ # We don't want Sinatra do setup any loggers for us. We will use our own.
271
+ set :logging, nil
272
+
273
+ # This is the app root...
274
+ set :root, lambda { GeneValidatorApp.root }
275
+
276
+ # This is the full path to the public folder...
277
+ set :public_folder, lambda { GeneValidatorApp.public_dir }
278
+ end
279
+
280
+ # Set up global variables for the templates...
281
+ before '/' do
282
+ @default_db = Database.default_db
283
+ @non_default_dbs = Database.non_default_dbs
284
+ @max_characters = GeneValidatorApp.max_characters
285
+ @current_gv_version = GeneValidator::VERSION
286
+ end
287
+
288
+ get '/' do
289
+ slim :index
290
+ end
291
+
292
+ post '/' do
293
+ cross_origin # Required for the API to work...
294
+ RunGeneValidator.init(request.url, params)
295
+ RunGeneValidator.run
296
+ end
297
+
298
+ # This error block will only ever be hit if the user gives us a funny
299
+ # sequence or incorrect advanced parameter. Well, we could hit this block
300
+ # if someone is playing around with our HTTP API too.
301
+ error RunGeneValidator::ArgumentError do
302
+ status 400
303
+ slim :"500", layout: false
304
+ end
305
+
306
+ # This will catch any unhandled error and some very special errors. Ideally
307
+ # we will never hit this block. If we do, there's a bug in GeneValidatorApp
308
+ # or something really weird going on.
309
+ # TODO: If we hit this error block we show the stacktrace to the user
310
+ # requesting them to post the same to our Google Group.
311
+ error Exception, RunGeneValidator::RuntimeError do
312
+ status 500 # TODO Create another template...
313
+ slim :"500", layout: false
314
+ end
315
+
316
+ not_found do
317
+ status 404
318
+ slim :"500" # TODO: Create another Template
319
+ end
320
+ end
321
+ end