wd_sinatra 0.0.1
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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +148 -0
- data/Rakefile +2 -0
- data/bin/wd_sinatra +47 -0
- data/lib/wd_sinatra.rb +7 -0
- data/lib/wd_sinatra/app_loader.rb +120 -0
- data/lib/wd_sinatra/sinatra_ext.rb +117 -0
- data/lib/wd_sinatra/test_helpers.rb +204 -0
- data/lib/wd_sinatra/version.rb +5 -0
- data/templates/Gemfile +23 -0
- data/templates/Guardfile +13 -0
- data/templates/Rakefile +32 -0
- data/templates/api/hello_world.rb +29 -0
- data/templates/bin/console +7 -0
- data/templates/config.ru +5 -0
- data/templates/config/app.rb +5 -0
- data/templates/config/environments/default.rb +3 -0
- data/templates/config/environments/production.rb +2 -0
- data/templates/config/environments/test.rb +3 -0
- data/templates/config/hooks.rb +74 -0
- data/templates/config/middleware.rb +0 -0
- data/templates/config/sinatra_config.rb +12 -0
- data/templates/lib/body_parser.rb +24 -0
- data/templates/lib/tasks/doc.rake +39 -0
- data/templates/lib/tasks/doc_generator/bootstrap/.gitignore +4 -0
- data/templates/lib/tasks/doc_generator/bootstrap/LICENSE +176 -0
- data/templates/lib/tasks/doc_generator/bootstrap/Makefile +47 -0
- data/templates/lib/tasks/doc_generator/bootstrap/README.md +105 -0
- data/templates/lib/tasks/doc_generator/bootstrap/bootstrap.css +2467 -0
- data/templates/lib/tasks/doc_generator/bootstrap/bootstrap.min.css +356 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/css/docs.css +317 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/ico/bootstrap-apple-114x114.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/ico/bootstrap-apple-57x57.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/ico/bootstrap-apple-72x72.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/ico/favicon.ico +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/bird.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/browsers.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/example-diagram-01.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/example-diagram-02.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/example-diagram-03.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/grid-18px.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/img/twitter-logo-no-bird.png +0 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/js/application.js +52 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/js/google-code-prettify/prettify.css +94 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/assets/js/google-code-prettify/prettify.js +28 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/index.html +2037 -0
- data/templates/lib/tasks/doc_generator/bootstrap/docs/javascript.html +798 -0
- data/templates/lib/tasks/doc_generator/bootstrap/examples/container-app.html +119 -0
- data/templates/lib/tasks/doc_generator/bootstrap/examples/fluid.html +122 -0
- data/templates/lib/tasks/doc_generator/bootstrap/examples/hero.html +79 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-alerts.js +124 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-buttons.js +64 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-dropdown.js +55 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-modal.js +260 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-popover.js +90 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-scrollspy.js +107 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-tabs.js +80 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/bootstrap-twipsy.js +321 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/index.html +40 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-alerts.js +41 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-buttons.js +42 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-dropdown.js +52 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-modal.js +151 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-popover.js +76 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-scrollspy.js +31 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-tabs.js +77 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/unit/bootstrap-twipsy.js +81 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/vendor/qunit.css +232 -0
- data/templates/lib/tasks/doc_generator/bootstrap/js/tests/vendor/qunit.js +1510 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/bootstrap.less +26 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/forms.less +479 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/mixins.less +222 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/patterns.less +1060 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/reset.less +141 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/scaffolding.less +139 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/tables.less +224 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/type.less +187 -0
- data/templates/lib/tasks/doc_generator/bootstrap/lib/variables.less +60 -0
- data/templates/lib/tasks/doc_generator/template.erb +117 -0
- data/templates/public/favicon.ico +0 -0
- data/wd-sinatra.gemspec +22 -0
- metadata +154 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2012 Matt Aimonetti
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Weasel Diesel Sinatra
|
|
2
|
+
|
|
3
|
+
Weasel-Diesel Sinatra app gem, allowing you to generate/update sinatra apps using the Weasel Diesel DSL
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
$ gem install 'wd_sinatra'
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
### App generation
|
|
13
|
+
|
|
14
|
+
Once the gem is installed, you can use the generator to create a new
|
|
15
|
+
app. Go to the location where you want to generate a new app and type
|
|
16
|
+
the following command (replace `<app_name>` by the name you want to
|
|
17
|
+
application to have):
|
|
18
|
+
|
|
19
|
+
$ wd_sinatra <app_name>
|
|
20
|
+
|
|
21
|
+
Check the newly generated app
|
|
22
|
+
|
|
23
|
+
$ cd <app_name>
|
|
24
|
+
|
|
25
|
+
You'll need bundler to install the dependencies:
|
|
26
|
+
|
|
27
|
+
$ gem install bundler
|
|
28
|
+
$ bundle install
|
|
29
|
+
|
|
30
|
+
### Starting the server
|
|
31
|
+
|
|
32
|
+
The app is now ready to use, to start it you can use rack:
|
|
33
|
+
|
|
34
|
+
$ bundle exec rackup
|
|
35
|
+
|
|
36
|
+
This will start the server on port 9292 and the default GET `/hello_world` service will be available at: `http://localhost:9292/hello_world'.
|
|
37
|
+
|
|
38
|
+
Note that the code won't be reloading automatically in the server when
|
|
39
|
+
you make a modification to the source code. For that, you might want to
|
|
40
|
+
use Puma + [Guard](https://github.com/jc00ke/guard-puma) or another tool that allows you to do that.
|
|
41
|
+
While it's a nice feature to have, a lot of developers like to do that
|
|
42
|
+
differently and it seems more sensitive to let them pick the way they
|
|
43
|
+
like the most.
|
|
44
|
+
|
|
45
|
+
### Console
|
|
46
|
+
|
|
47
|
+
$ bundle exec bin/console
|
|
48
|
+
|
|
49
|
+
The console mode is like the server mode but without the server only
|
|
50
|
+
concerns such as the sinatra routes config and Rack middleware.
|
|
51
|
+
|
|
52
|
+
### Documentation generation
|
|
53
|
+
|
|
54
|
+
$ rake doc:services
|
|
55
|
+
|
|
56
|
+
To generate documentation for the APIs you created in the api folder.
|
|
57
|
+
|
|
58
|
+
### Testing
|
|
59
|
+
|
|
60
|
+
TODO
|
|
61
|
+
|
|
62
|
+
## Writing a service
|
|
63
|
+
|
|
64
|
+
TODO see Weasel Diesel for now.
|
|
65
|
+
|
|
66
|
+
## Config and hooks
|
|
67
|
+
|
|
68
|
+
### app.rb
|
|
69
|
+
|
|
70
|
+
The `config/app.rb` file is being required after the environment is set
|
|
71
|
+
but before the models are loaded. This is the perfect place to load
|
|
72
|
+
custom libraries and set your datastore.
|
|
73
|
+
|
|
74
|
+
This is where you will for instance load ActiveRecord and set your DB
|
|
75
|
+
connection.
|
|
76
|
+
|
|
77
|
+
### Environments
|
|
78
|
+
|
|
79
|
+
The files in `config/environments` can
|
|
80
|
+
be used to set environment specific configuration or other.
|
|
81
|
+
If you add a new environment such as staging, you can add a `staging.rb`
|
|
82
|
+
file in the environments folder that will only get required when running
|
|
83
|
+
in this env mode.
|
|
84
|
+
Whatever the environment is, the `config/environments/default.rb` is
|
|
85
|
+
being required before the specific env file.
|
|
86
|
+
|
|
87
|
+
### Hooks
|
|
88
|
+
|
|
89
|
+
The request dispatcher offers 3 hooks which you can see demonstrated in
|
|
90
|
+
`config/hooks.rb`.
|
|
91
|
+
|
|
92
|
+
* `params_preprocessor_hook(params)`
|
|
93
|
+
* `params_postprocessor_hook(params)`
|
|
94
|
+
* `pre_dispatch_hook`
|
|
95
|
+
|
|
96
|
+
The two first hooks are used to process the params and when implemented
|
|
97
|
+
are expected to return the params that will be used in the request.
|
|
98
|
+
|
|
99
|
+
The `pre_dispatch_hook` is called just before the request is dispatched
|
|
100
|
+
to the service implementation. This is where you might want to implement
|
|
101
|
+
an authentication verification system for instance.
|
|
102
|
+
|
|
103
|
+
These 3 hooks have access to the entire request context, including the
|
|
104
|
+
`service` being called. You can use the service `extra` option to set
|
|
105
|
+
some custom settings that can then be used in this pre dispatch hook.
|
|
106
|
+
|
|
107
|
+
In the default generated application, a body parser is provided to parse
|
|
108
|
+
JSON requests when the HTTP verb is PUT, POST or DELETE. The json parser is set by default to use the `JSON` module but you might want to change it to use Yajl for instance.
|
|
109
|
+
To do that, edit the `config/hooks.rb` file and change the following:
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
BodyParser.json_parser = JSON
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
to:
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
BodyParser.json_parser = Yajl::Parser
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Of course, you'll need to require `Yajl` first and add it to your
|
|
122
|
+
Gemfile if you want to use Bundler.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
## Using an ORM
|
|
127
|
+
|
|
128
|
+
TODO: see https://github.com/mattetti/sinatra-web-api-example/ for now
|
|
129
|
+
for an example of setting up ActiveRecord.
|
|
130
|
+
Eventually the generator will take an option to generate an AR, DM or
|
|
131
|
+
other ORM template.
|
|
132
|
+
|
|
133
|
+
## Update
|
|
134
|
+
|
|
135
|
+
To update your app, just update your gem dependency on `wd_sinatra`, you
|
|
136
|
+
can also compare the difference between your app and a freshly generated
|
|
137
|
+
app by trying to generate a new app named the same as your old app.
|
|
138
|
+
The generator will detect conflicts and let you pick an action (diff,
|
|
139
|
+
overwrite, ignore...)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
## Contributing
|
|
143
|
+
|
|
144
|
+
1. Fork it
|
|
145
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
146
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
147
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
148
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/wd_sinatra
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require "rubygems"
|
|
3
|
+
require "thor/group"
|
|
4
|
+
|
|
5
|
+
class WdSinatra < Thor::Group
|
|
6
|
+
include Thor::Actions
|
|
7
|
+
|
|
8
|
+
# Define arguments and options
|
|
9
|
+
# argument :type, :type => :string, :desc => "The type to generate, app by default"
|
|
10
|
+
argument :name, :type => :string, :desc => "The name of the app to generate"
|
|
11
|
+
class_option :test_framework, :default => :test_unit
|
|
12
|
+
|
|
13
|
+
def self.source_root
|
|
14
|
+
File.expand_path(File.join('..', 'templates'), File.dirname(__FILE__))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_lib_directory
|
|
18
|
+
directory "lib", "#{name}/lib"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_config_directory
|
|
22
|
+
directory "config", "#{name}/config"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create_bin_directory
|
|
26
|
+
directory "bin", "#{name}/bin"
|
|
27
|
+
chmod "#{name}/bin/console", 0755
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create_public_directory
|
|
31
|
+
directory "public", "#{name}/public"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create_api_directory
|
|
35
|
+
directory "api", "#{name}/api"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_files
|
|
39
|
+
copy_file "Rakefile", "#{name}/Rakefile"
|
|
40
|
+
copy_file "Gemfile", "#{name}/Gemfile"
|
|
41
|
+
copy_file "config.ru", "#{name}/config.ru"
|
|
42
|
+
copy_file "Guardfile", "#{name}/Guardfile"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
WdSinatra.start
|
data/lib/wd_sinatra.rb
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
if RUBY_VERSION =~ /1.8/
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'backports'
|
|
4
|
+
end
|
|
5
|
+
require 'bundler'
|
|
6
|
+
Bundler.setup
|
|
7
|
+
require 'logger'
|
|
8
|
+
require 'weasel_diesel'
|
|
9
|
+
|
|
10
|
+
module WDSinatra
|
|
11
|
+
module AppLoader
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
# Boot in server mode
|
|
15
|
+
def server(root_path)
|
|
16
|
+
@root = root_path
|
|
17
|
+
unless @booted
|
|
18
|
+
console(root_path)
|
|
19
|
+
load_middleware
|
|
20
|
+
set_sinatra_routes
|
|
21
|
+
set_sinatra_settings
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Boot in console mode
|
|
26
|
+
def console(root_path)
|
|
27
|
+
@root = root_path
|
|
28
|
+
unless @booted
|
|
29
|
+
set_env
|
|
30
|
+
set_loadpath
|
|
31
|
+
load_environment
|
|
32
|
+
load_lib_dependencies
|
|
33
|
+
load_app_config
|
|
34
|
+
load_models
|
|
35
|
+
load_apis
|
|
36
|
+
@booted = true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def root_path
|
|
41
|
+
@root
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# PRIVATE
|
|
45
|
+
|
|
46
|
+
# Sets the environment (RACK_ENV) based on some env variables.
|
|
47
|
+
def set_env
|
|
48
|
+
if !Object.const_defined?(:RACK_ENV)
|
|
49
|
+
ENV['RACK_ENV'] ||= ENV['RAILS_ENV'] || 'development'
|
|
50
|
+
Object.const_set(:RACK_ENV, ENV['RACK_ENV'])
|
|
51
|
+
end
|
|
52
|
+
puts "Running in #{RACK_ENV} mode" if RACK_ENV == 'development'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Loads an environment specific config if available, the config file is where the logger should be set
|
|
57
|
+
# if it was not, we are using stdout.
|
|
58
|
+
def load_environment(env=RACK_ENV)
|
|
59
|
+
# Load the default which can be overwritten or extended by specific
|
|
60
|
+
# env config files.
|
|
61
|
+
require File.join(root_path, 'config', 'environments', 'default.rb')
|
|
62
|
+
env_file = File.join(root_path, "config", "environments", "#{env}.rb")
|
|
63
|
+
if File.exist?(env_file)
|
|
64
|
+
require env_file
|
|
65
|
+
else
|
|
66
|
+
debug_msg = "Environment file: #{env_file} couldn't be found, using only the default environment config instead." unless env == 'development'
|
|
67
|
+
end
|
|
68
|
+
# making sure we have a LOGGER constant defined.
|
|
69
|
+
unless Object.const_defined?(:LOGGER)
|
|
70
|
+
Object.const_set(:LOGGER, Logger.new($stdout))
|
|
71
|
+
end
|
|
72
|
+
LOGGER.debug(debug_msg) if debug_msg
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def set_loadpath(root=nil)
|
|
76
|
+
root ||= root_path
|
|
77
|
+
$: << root
|
|
78
|
+
$: << File.join(root, 'lib')
|
|
79
|
+
$: << File.join(root, 'models')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def load_lib_dependencies
|
|
83
|
+
# WeaselDiesel is the web service DSL gem used to define services.
|
|
84
|
+
require 'weasel_diesel'
|
|
85
|
+
require 'sinatra'
|
|
86
|
+
require 'wd_sinatra/sinatra_ext'
|
|
87
|
+
# TODO: hook to custom app dependencies
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def load_app_config
|
|
91
|
+
require File.join(root_path, 'config', 'app')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def load_models
|
|
95
|
+
Dir.glob(File.join(root_path, "models", "**", "*.rb")).each do |model|
|
|
96
|
+
require model
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# DSL routes are located in the api folder
|
|
101
|
+
def load_apis
|
|
102
|
+
Dir.glob(File.join(root_path, "api", "**", "*.rb")).each do |api|
|
|
103
|
+
require api
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def set_sinatra_routes
|
|
108
|
+
WSList.all.sort.each{|api| api.load_sinatra_route }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def load_middleware
|
|
112
|
+
require File.join(root_path, 'config', 'middleware')
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def set_sinatra_settings
|
|
116
|
+
require File.join(root_path, 'config', 'sinatra_config')
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'params_verification'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
class WeaselDiesel
|
|
6
|
+
|
|
7
|
+
class RequestHandler
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
# @return [WeaselDiesel] The service served by this controller
|
|
11
|
+
# @api public
|
|
12
|
+
attr_reader :service
|
|
13
|
+
|
|
14
|
+
# @return [Sinatra::Application]
|
|
15
|
+
# @api public
|
|
16
|
+
attr_reader :app
|
|
17
|
+
|
|
18
|
+
# @return [Hash]
|
|
19
|
+
# @api public
|
|
20
|
+
attr_reader :env
|
|
21
|
+
|
|
22
|
+
# @return [Sinatra::Request]
|
|
23
|
+
# @see http://rubydoc.info/github/sinatra/sinatra/Sinatra/Request
|
|
24
|
+
# @api public
|
|
25
|
+
attr_reader :request
|
|
26
|
+
|
|
27
|
+
# @return [Sinatra::Response]
|
|
28
|
+
# @see http://rubydoc.info/github/sinatra/sinatra/Sinatra/Response
|
|
29
|
+
# @api public
|
|
30
|
+
attr_reader :response
|
|
31
|
+
|
|
32
|
+
# @return [Hash]
|
|
33
|
+
# @api public
|
|
34
|
+
attr_accessor :params
|
|
35
|
+
|
|
36
|
+
attr_accessor :current_user
|
|
37
|
+
|
|
38
|
+
# The service controller might be loaded outside of a Sinatra App
|
|
39
|
+
# in this case, we don't need to load the helpers
|
|
40
|
+
if Object.const_defined?(:Sinatra)
|
|
41
|
+
include Sinatra::Helpers
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def initialize(service, &block)
|
|
45
|
+
@service = service
|
|
46
|
+
@implementation = block
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def dispatch(app)
|
|
50
|
+
@app = app
|
|
51
|
+
@env = app.env
|
|
52
|
+
@request = app.request
|
|
53
|
+
@response = app.response
|
|
54
|
+
@service = service
|
|
55
|
+
|
|
56
|
+
begin
|
|
57
|
+
# raises an exception if the params are not valid
|
|
58
|
+
# otherwise update the app params with potentially new params (using default values)
|
|
59
|
+
# note that if a type is mentioned for a params, the object will be cast to this object type
|
|
60
|
+
#
|
|
61
|
+
# removing the fake sinatra params since v1.3 added this. (should be eventually removed)
|
|
62
|
+
if app.params['splat']
|
|
63
|
+
processed_params = app.params.dup
|
|
64
|
+
processed_params.delete('splat')
|
|
65
|
+
processed_params.delete('captures')
|
|
66
|
+
end
|
|
67
|
+
@params = (processed_params || app.params)
|
|
68
|
+
@params = params_preprocessor_hook(@params) if self.respond_to?(:params_preprocessor_hook)
|
|
69
|
+
@params = ParamsVerification.validate!(@params, service.defined_params)
|
|
70
|
+
@params = params_postrocessor_hook(@params) if self.respond_to?(:params_postprocessor_hook)
|
|
71
|
+
rescue Exception => e
|
|
72
|
+
LOGGER.error e.message
|
|
73
|
+
LOGGER.error "passed params: #{app.params.inspect}"
|
|
74
|
+
halt 400, {:error => e.message}.to_json
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Define WeaselDiesel::RequestHandler#authorization_check in your app if
|
|
78
|
+
# you want to use an auth check.
|
|
79
|
+
pre_dispatch_hook if self.respond_to?(:pre_dispatch_hook)
|
|
80
|
+
service_dispatch
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Forwarding some methods to the underlying app object
|
|
84
|
+
def_delegators :app, :settings, :halt, :compile_template, :session
|
|
85
|
+
|
|
86
|
+
private ##################################################
|
|
87
|
+
|
|
88
|
+
end # of RequestHandler
|
|
89
|
+
|
|
90
|
+
attr_reader :handler
|
|
91
|
+
|
|
92
|
+
def implementation(&block)
|
|
93
|
+
if block_given?
|
|
94
|
+
@handler = RequestHandler.new(self, &block)
|
|
95
|
+
@handler.define_singleton_method(:service_dispatch, block)
|
|
96
|
+
end
|
|
97
|
+
@handler
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def load_sinatra_route
|
|
101
|
+
service = self
|
|
102
|
+
upcase_verb = service.verb.to_s.upcase
|
|
103
|
+
unless ENV['DONT_PRINT_ROUTES']
|
|
104
|
+
LOGGER.info "Available endpoint: #{self.http_verb.upcase} /#{self.url}"
|
|
105
|
+
end
|
|
106
|
+
raise "DSL is missing the implementation block" unless self.handler && self.handler.respond_to?(:service_dispatch)
|
|
107
|
+
|
|
108
|
+
# Define the route directly to save some object allocations on the critical path
|
|
109
|
+
# Note that we are using a private API to define the route and that unlike sinatra usual DSL
|
|
110
|
+
# we do NOT define a HEAD route for every GET route.
|
|
111
|
+
Sinatra::Base.send(:route, upcase_verb, "/#{self.url}") do
|
|
112
|
+
service.handler.dispatch(self)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|