praxis 0.10.1 → 0.11pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/CHANGELOG.md +47 -10
- data/Gemfile +1 -1
- data/Guardfile +1 -0
- data/bin/praxis +33 -4
- data/lib/api_browser/app/css/main.css +0 -3
- data/lib/praxis.rb +16 -0
- data/lib/praxis/action_definition.rb +16 -18
- data/lib/praxis/application.rb +31 -2
- data/lib/praxis/bootloader.rb +37 -4
- data/lib/praxis/bootloader_stages/environment.rb +3 -7
- data/lib/praxis/bootloader_stages/plugin_config_load.rb +20 -0
- data/lib/praxis/bootloader_stages/plugin_config_prepare.rb +18 -0
- data/lib/praxis/bootloader_stages/plugin_loader.rb +19 -0
- data/lib/praxis/bootloader_stages/plugin_setup.rb +13 -0
- data/lib/praxis/bootloader_stages/routing.rb +16 -6
- data/lib/praxis/callbacks.rb +0 -2
- data/lib/praxis/config.rb +3 -2
- data/lib/praxis/dispatcher.rb +25 -13
- data/lib/praxis/error_handler.rb +16 -0
- data/lib/praxis/links.rb +9 -4
- data/lib/praxis/media_type_collection.rb +2 -3
- data/lib/praxis/notifications.rb +41 -0
- data/lib/praxis/plugin.rb +18 -8
- data/lib/praxis/plugin_concern.rb +40 -0
- data/lib/praxis/request.rb +27 -7
- data/lib/praxis/request_stages/action.rb +7 -2
- data/lib/praxis/request_stages/response.rb +7 -3
- data/lib/praxis/request_stages/validate_payload.rb +7 -1
- data/lib/praxis/resource_definition.rb +37 -16
- data/lib/praxis/response.rb +1 -0
- data/lib/praxis/responses/internal_server_error.rb +13 -8
- data/lib/praxis/responses/validation_error.rb +10 -7
- data/lib/praxis/restful_doc_generator.rb +312 -0
- data/lib/praxis/router.rb +7 -5
- data/lib/praxis/skeletor/restful_routing_config.rb +12 -5
- data/lib/praxis/stage.rb +5 -1
- data/lib/praxis/stats.rb +106 -0
- data/lib/praxis/tasks/api_docs.rb +8 -314
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +4 -1
- data/spec/functional_spec.rb +87 -32
- data/spec/praxis/action_definition_spec.rb +13 -12
- data/spec/praxis/bootloader_spec.rb +12 -5
- data/spec/praxis/notifications_spec.rb +23 -0
- data/spec/praxis/plugin_concern_spec.rb +21 -0
- data/spec/praxis/request_spec.rb +56 -1
- data/spec/praxis/request_stages_validate_spec.rb +3 -3
- data/spec/praxis/resource_definition_spec.rb +44 -60
- data/spec/praxis/responses/internal_server_error_spec.rb +32 -16
- data/spec/praxis/restful_routing_config_spec.rb +15 -2
- data/spec/praxis/router_spec.rb +5 -3
- data/spec/praxis/stats_spec.rb +9 -0
- data/spec/praxis_mapper_plugin_spec.rb +71 -0
- data/spec/spec_app/app/controllers/instances.rb +12 -0
- data/spec/spec_app/app/controllers/volumes.rb +5 -0
- data/spec/spec_app/app/models/person.rb +3 -0
- data/spec/spec_app/config/active_record.yml +2 -0
- data/spec/spec_app/config/authentication.yml +3 -0
- data/spec/spec_app/config/authorization.yml +4 -0
- data/spec/spec_app/config/environment.rb +28 -1
- data/spec/spec_app/config/praxis_mapper.yml +6 -0
- data/spec/spec_app/config/sequel_model.yml +2 -0
- data/spec/spec_app/config/stats.yml +8 -0
- data/spec/spec_app/config/stats.yml.dis +8 -0
- data/spec/spec_app/design/resources/instances.rb +53 -16
- data/spec/spec_app/design/resources/volumes.rb +13 -2
- data/spec/spec_helper.rb +14 -0
- data/spec/support/spec_authentication_plugin.rb +126 -0
- data/spec/support/spec_authorization_plugin.rb +95 -0
- data/spec/support/spec_praxis_mapper_plugin.rb +157 -0
- data/tasks/loader.thor +6 -0
- data/tasks/thor/app.rb +48 -0
- data/tasks/thor/example.rb +283 -0
- data/tasks/thor/templates/generator/empty_app/.gitignore +3 -0
- data/tasks/thor/templates/generator/empty_app/.rspec +1 -0
- data/tasks/thor/templates/generator/empty_app/Gemfile +29 -0
- data/tasks/thor/templates/generator/empty_app/Guardfile +3 -0
- data/tasks/thor/templates/generator/empty_app/README.md +4 -0
- data/tasks/thor/templates/generator/empty_app/Rakefile +25 -0
- data/tasks/thor/templates/generator/empty_app/app/models/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/app/models/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/app/responses/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/app/responses/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/app/v1/controllers/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/app/v1/controllers/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/config.ru +7 -0
- data/tasks/thor/templates/generator/empty_app/config/environment.rb +17 -0
- data/tasks/thor/templates/generator/empty_app/config/rainbows.rb +57 -0
- data/tasks/thor/templates/generator/empty_app/design/api.rb +0 -0
- data/tasks/thor/templates/generator/empty_app/design/response_templates/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/design/response_templates/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/media_types/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/media_types/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/resources/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/resources/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/spec/spec_helper.rb +18 -0
- metadata +97 -6
- data/tasks/praxis_app_generator.thor +0 -307
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5925b03e5020e28fc79530a6991c3f030897996d
|
4
|
+
data.tar.gz: f301a81c0628df629ae32e805debbb653b0c2477
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f573ece40063959ee3df1a11db4a36563acd44c68bc7ad70192f90bb8268501b4c128e504ba8080406037303a6fa5dbbf4a854d741843c80aae559df6b2a0f63
|
7
|
+
data.tar.gz: 3adb04192e7414e607482a44f2a8f9f83618dee6b0202094ee77c77d4d46ae0dd63e5579dd55e87ed76aa6212a0a294229108d8c5bd8d8bd841de417cf73fb63
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,49 @@
|
|
1
1
|
# praxis changelog
|
2
2
|
|
3
|
-
##
|
3
|
+
## 0.11
|
4
4
|
|
5
|
-
*
|
5
|
+
* `MediaTypeCollection`:
|
6
|
+
* Added support for loading `decorate`ed `Resource` associations.
|
7
|
+
* Refined and enhanced support for API versioning:
|
8
|
+
* version DSL now can take a `using` option which specifies and array of the methods are allowed: `:header`,`:params`,`:path`(new)
|
9
|
+
* if not specified, it will default to `using: [:header, :params]` (so that the version can be passed to the header OR the params)
|
10
|
+
* the new `:path` option will build the action routes by prefixing the version given a common pattern (i.e., "/v1.0/...")
|
11
|
+
* The effects of path versioning will be visible through `rake praxis:routes`
|
12
|
+
* the default api prefix pattern is ("/v(version)/") but can changed by either
|
13
|
+
* overriding ``Praxis::Request.path_version_prefix` and return the appropriate string prefix (i.e., by default this returns "/v")
|
14
|
+
* or overriding `Praxis::Request.path_version_matcher` and providing the fully custom matching regexp. This regexp must have a capture (named `version`) that would return matched version value.
|
15
|
+
* Enhanced praxis generator:
|
16
|
+
* Added a new generator (available through `praxis new app_name`) which creates a blank new app, with enough basic structure and setup to start building an API.
|
17
|
+
* Changed the example hello world generation command. Instead of `praxis generate app_name`, it is now available through `praxis example app_name`
|
18
|
+
* Changed the path lookup for the praxis directory (to not use installed gems, which could be multiple). [Issue #67]
|
19
|
+
* `ResourceDefinition`:
|
20
|
+
* Added: `action_defaults` method, to define default options for actions. May be called more than once.
|
21
|
+
* Removed: `params`, `payload`, `headers`, and `response`. Specify these inside `action_defaults` instead.
|
22
|
+
* `Application`:
|
23
|
+
* Added `middleware` method to use Rack middleware.
|
24
|
+
* `ErrorHandler`
|
25
|
+
* It is now possible to register the error handler class to be invoked when an uncaught exception is thrown by setting `Application#error_handler`.
|
26
|
+
* The default error handler writes the error and backtrace into the Praxis logger, and returns an `InternalServerError` response
|
27
|
+
* Added `Praxis::Notifications` framework backed by ActiveSupport::Notifications
|
28
|
+
* Its interface is the same as AS::Notifications (.publish, .instrument, .subscribe, and etc.)
|
29
|
+
* Each incoming rack request is instrumented as `rack.request.all`, with a payload of `{response: response}`, where `response` is the `Response` object that will be returned to the client. Internally, Praxis subscribes to this to generate timing statistics with `Praxis::Stats`.
|
30
|
+
* Additionally, each request that is dispatched to an action is instrumented as `praxis.request.all`, with a payload of `{request: request, response: response}`, where `response` is as above, and `request` is the `Request` object for the request.
|
31
|
+
* Added `Praxis::Stats` framework backed by `Harness` (i.e. a statsd interface)
|
32
|
+
* Can be configured with a collector type (fake, Statsd) and an asynchronous queue + thread
|
33
|
+
* Wraps the statsd interface: count, increment, decrement, time ...
|
34
|
+
* Added a new `decorate_docs` method to enhance generated JSON docs for actions in `ResourceDefinitions`
|
35
|
+
* Using this hook, anybody can register a block that can change/enhance the JSON structure of generated documents for any given action
|
36
|
+
* Added a brand new Plugins architecture
|
37
|
+
* Plugins can easily inject code in the Request, Controller, ResourceDefinition or ActionDefinition
|
38
|
+
* Can be instances or singletons (and will be initialized correspondingly)
|
39
|
+
* Plugins can be easily configured under a unique "config key" in the Praxis config
|
40
|
+
* See the [Plugins](http://praxis-framework.io/reference/plugins/) section in the documentation for more information.
|
41
|
+
* Added a Plugin for using the Praxis::Mapper gem
|
42
|
+
* Configurable through a simple `praxis_mapper.yml` file
|
43
|
+
* Its supports several repositories (by name)
|
44
|
+
* Each repository can be of a different type (default is sequel)
|
45
|
+
* `praxis:doc_browser` rake task now takes a port argument for specifying the port to run on, e.g. `rake praxis:doc_browser[9000]` to run on port 9000.
|
46
|
+
* Added `show_exceptions` configuration option to to control default ErrorHandler behavior.
|
6
47
|
|
7
48
|
## 0.10.0
|
8
49
|
|
@@ -22,7 +63,7 @@
|
|
22
63
|
* Fixes [Issue #21](https://github.com/rightscale/praxis/issues/21)
|
23
64
|
* Introduced `around` filters using blocks:
|
24
65
|
* Around filters can be set wrapping any of the request stages (load, validate, action...) and might apply to only certain actions (i.e. exactly the same as the before/after filters)
|
25
|
-
* Therefore they supports the same attributes as `before` and `after` filters. The only difference is that an around filter block will get an extra parameter with the block to call to continue the chain.
|
66
|
+
* Therefore they supports the same attributes as `before` and `after` filters. The only difference is that an around filter block will get an extra parameter with the block to call to continue the chain.
|
26
67
|
* See the [Instances](https://github.com/rightscale/praxis/blob/master/spec/spec_app/app/controllers/instances.rb) controller for examples.
|
27
68
|
* Fix: Change :created response template to take an optiona ‘location’ parameter (instead of a media_type one, since it doesn’t make sense for a 201 type response) [Issue #26](https://github.com/rightscale/praxis/issues/23)
|
28
69
|
* Make the system be more robust in error reporting when controllers do not return a String or a Response
|
@@ -41,11 +82,7 @@
|
|
41
82
|
* `MediaTypeCollection`. See [volume_snapshot](spec/spec_app/design/media_types/volume_snapshot.rb) in the specs for an example.
|
42
83
|
* Added `member_view` DSL to define a view that renders the collection's members with the given view.
|
43
84
|
* Change: Now requires all views to be explicitly defined (and will not automatically use the underlying member view if it exists). To define a view for member element (wrapping it in a collection) one can use the new member_view.
|
44
|
-
*
|
45
|
-
|
46
|
-
|
47
|
-
** Header keys are case sensitive now (although Praxis gracefully allows loading the uppercased RACK names )
|
48
|
-
* Added tests for using `Attributor::Hash` attributes that can accept "extra" keys:
|
49
|
-
** See the `bulk_create` action for an example applied to `Praxis::Multipart` (which derives from `Attributor::Hash`) payload [here](https://github.com/rightscale/praxis/blob/master/spec/spec_app/design/resources/instances.rb).
|
50
|
-
|
85
|
+
*
|
86
|
+
|
87
|
+
|
51
88
|
## 0.9 Initial release
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
data/bin/praxis
CHANGED
@@ -2,9 +2,38 @@
|
|
2
2
|
|
3
3
|
require 'bundler'
|
4
4
|
|
5
|
-
path_to_praxis
|
6
|
-
|
5
|
+
path_to_praxis = File.expand_path(File.dirname(File.dirname(__FILE__)))
|
6
|
+
path_to_loader = '%s/tasks/loader.thor' % path_to_praxis
|
7
7
|
|
8
|
-
load
|
8
|
+
load path_to_loader
|
9
9
|
|
10
|
-
|
10
|
+
class PraxisGenerator < Thor
|
11
|
+
|
12
|
+
# Simple helper to go get the existing description for the real action
|
13
|
+
# Usage must still be provided rather than retrieved (since it is not a
|
14
|
+
# straight "usage" from the remote action when arguments are defined )
|
15
|
+
def self.desc_for( usage_string, klass, action_name, description_prefix="")
|
16
|
+
action_name = action_name.to_s
|
17
|
+
cmd = klass.commands[action_name]
|
18
|
+
raise "Error, could not find description for #{klass.name}##{action_name}" if cmd.nil?
|
19
|
+
desc usage_string, "#{description_prefix}#{cmd.description}"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc_for "new APP_NAME", ::PraxisGen::App, :new
|
23
|
+
def new(app_name)
|
24
|
+
::PraxisGen::App.start(['new' , app_name])
|
25
|
+
end
|
26
|
+
|
27
|
+
desc_for "example APP_NAME", ::PraxisGen::Example, :new
|
28
|
+
def example(app_name)
|
29
|
+
::PraxisGen::Example.start(['new', app_name])
|
30
|
+
end
|
31
|
+
|
32
|
+
desc_for "generate APP_NAME", ::PraxisGen::Example, :new, "DEPRECATED!: "
|
33
|
+
def generate(app_name)
|
34
|
+
warn "This is a deprecated method.\nTo generate a hello world example, please use:\n praxis example #{app_name} "
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
PraxisGenerator.start(ARGV)
|
data/lib/praxis.rb
CHANGED
@@ -3,6 +3,8 @@ require 'attributor'
|
|
3
3
|
require 'praxis-mapper'
|
4
4
|
require 'praxis-blueprints'
|
5
5
|
|
6
|
+
require 'active_support/concern'
|
7
|
+
|
6
8
|
$:.unshift File.dirname(__FILE__)
|
7
9
|
|
8
10
|
module Attributor
|
@@ -24,6 +26,7 @@ module MIME
|
|
24
26
|
end
|
25
27
|
|
26
28
|
module Praxis
|
29
|
+
|
27
30
|
autoload :ActionDefinition, 'praxis/action_definition'
|
28
31
|
autoload :ApiDefinition, 'praxis/api_definition'
|
29
32
|
autoload :Application, 'praxis/application'
|
@@ -32,9 +35,11 @@ module Praxis
|
|
32
35
|
autoload :Controller, 'praxis/controller'
|
33
36
|
autoload :Callbacks, 'praxis/callbacks'
|
34
37
|
autoload :Dispatcher, 'praxis/dispatcher'
|
38
|
+
autoload :ErrorHandler, 'praxis/error_handler'
|
35
39
|
autoload :Exception, 'praxis/exception'
|
36
40
|
autoload :FileGroup,'praxis/file_group'
|
37
41
|
autoload :Plugin, 'praxis/plugin'
|
42
|
+
autoload :PluginConcern, 'praxis/plugin_concern'
|
38
43
|
autoload :Request, 'praxis/request'
|
39
44
|
autoload :ResourceDefinition, 'praxis/resource_definition'
|
40
45
|
autoload :Response, 'praxis/response'
|
@@ -46,6 +51,11 @@ module Praxis
|
|
46
51
|
autoload :Stage, 'praxis/stage'
|
47
52
|
autoload :ContentTypeParser, 'praxis/content_type_parser'
|
48
53
|
|
54
|
+
autoload :Stats, 'praxis/stats'
|
55
|
+
autoload :Notifications, 'praxis/notifications'
|
56
|
+
|
57
|
+
autoload :RestfulDocGenerator, 'praxis/restful_doc_generator'
|
58
|
+
|
49
59
|
# types
|
50
60
|
autoload :Links, 'praxis/links'
|
51
61
|
autoload :MediaType, 'praxis/media_type'
|
@@ -79,6 +89,12 @@ module Praxis
|
|
79
89
|
module BootloaderStages
|
80
90
|
autoload :FileLoader, 'praxis/bootloader_stages/file_loader'
|
81
91
|
autoload :Environment, 'praxis/bootloader_stages/environment'
|
92
|
+
|
93
|
+
autoload :PluginLoader, 'praxis/bootloader_stages/plugin_loader'
|
94
|
+
autoload :PluginConfigPrepare, 'praxis/bootloader_stages/plugin_config_prepare'
|
95
|
+
autoload :PluginConfigLoad, 'praxis/bootloader_stages/plugin_config_load'
|
96
|
+
autoload :PluginSetup, 'praxis/bootloader_stages/plugin_setup'
|
97
|
+
|
82
98
|
autoload :SubgroupLoader, 'praxis/bootloader_stages/subgroup_loader'
|
83
99
|
autoload :WarnUnloadedFiles, 'praxis/bootloader_stages/warn_unloaded_files'
|
84
100
|
autoload :Routing, 'praxis/bootloader_stages/routing'
|
@@ -16,6 +16,16 @@ module Praxis
|
|
16
16
|
attr_reader :named_routes
|
17
17
|
attr_reader :responses
|
18
18
|
|
19
|
+
class << self
|
20
|
+
attr_accessor :doc_decorations
|
21
|
+
end
|
22
|
+
|
23
|
+
@doc_decorations = []
|
24
|
+
|
25
|
+
def self.decorate_docs(&callback)
|
26
|
+
self.doc_decorations << callback
|
27
|
+
end
|
28
|
+
|
19
29
|
def initialize(name, resource_definition, **opts, &block)
|
20
30
|
@name = name
|
21
31
|
@resource_definition = resource_definition
|
@@ -27,23 +37,8 @@ module Praxis
|
|
27
37
|
end
|
28
38
|
end
|
29
39
|
|
30
|
-
|
31
|
-
|
32
|
-
params(saved_type, saved_opts, &saved_block)
|
33
|
-
end
|
34
|
-
|
35
|
-
if resource_definition.payload
|
36
|
-
saved_type, saved_opts, saved_block = resource_definition.payload
|
37
|
-
payload(saved_type, saved_opts, &saved_block)
|
38
|
-
end
|
39
|
-
|
40
|
-
if resource_definition.headers
|
41
|
-
saved_opts, saved_block = resource_definition.headers
|
42
|
-
headers(saved_opts, &saved_block)
|
43
|
-
end
|
44
|
-
|
45
|
-
resource_definition.responses.each do |name, args|
|
46
|
-
response(name, args)
|
40
|
+
resource_definition.action_defaults.each do |defaults|
|
41
|
+
self.instance_eval(&defaults)
|
47
42
|
end
|
48
43
|
|
49
44
|
self.instance_eval(&block) if block_given?
|
@@ -141,13 +136,13 @@ module Praxis
|
|
141
136
|
end
|
142
137
|
end
|
143
138
|
|
139
|
+
|
144
140
|
def description(text = nil)
|
145
141
|
@description = text if text
|
146
142
|
@description
|
147
143
|
end
|
148
144
|
|
149
145
|
|
150
|
-
|
151
146
|
def describe
|
152
147
|
{}.tap do |hash|
|
153
148
|
hash[:description] = description
|
@@ -161,6 +156,9 @@ module Praxis
|
|
161
156
|
memo[response.name] = response.describe
|
162
157
|
memo
|
163
158
|
end
|
159
|
+
self.class.doc_decorations.each do |callback|
|
160
|
+
callback.call(self, hash)
|
161
|
+
end
|
164
162
|
end
|
165
163
|
end
|
166
164
|
|
data/lib/praxis/application.rb
CHANGED
@@ -9,6 +9,8 @@ module Praxis
|
|
9
9
|
attr_reader :router
|
10
10
|
attr_reader :controllers
|
11
11
|
attr_reader :resource_definitions
|
12
|
+
attr_reader :app
|
13
|
+
attr_reader :builder
|
12
14
|
|
13
15
|
attr_accessor :bootloader
|
14
16
|
attr_accessor :file_layout
|
@@ -16,6 +18,8 @@ module Praxis
|
|
16
18
|
attr_accessor :logger
|
17
19
|
attr_accessor :plugins
|
18
20
|
attr_accessor :root
|
21
|
+
attr_accessor :error_handler
|
22
|
+
|
19
23
|
|
20
24
|
def self.configure
|
21
25
|
yield(self.instance)
|
@@ -25,11 +29,16 @@ module Praxis
|
|
25
29
|
@controllers = Set.new
|
26
30
|
@resource_definitions = Set.new
|
27
31
|
|
32
|
+
@error_handler = ErrorHandler.new
|
33
|
+
|
28
34
|
@router = Router.new(self)
|
29
35
|
|
36
|
+
@builder = Rack::Builder.new
|
37
|
+
@app = nil
|
38
|
+
|
30
39
|
@bootloader = Bootloader.new(self)
|
31
40
|
@file_layout = nil
|
32
|
-
@plugins =
|
41
|
+
@plugins = Hash.new
|
33
42
|
@loaded_files = Set.new
|
34
43
|
@config = Config.new
|
35
44
|
@root = nil
|
@@ -40,11 +49,30 @@ module Praxis
|
|
40
49
|
@root = Pathname.new(root).expand_path
|
41
50
|
|
42
51
|
@bootloader.setup!
|
52
|
+
|
53
|
+
@builder.run(@router)
|
54
|
+
@app = @builder.to_app
|
55
|
+
|
56
|
+
Notifications.subscribe 'rack.request.all'.freeze do |name, start, finish, _id, payload|
|
57
|
+
duration = (finish - start) * 1000
|
58
|
+
Stats.timing(name, duration)
|
59
|
+
|
60
|
+
status, _, _ = payload[:response]
|
61
|
+
Stats.increment "rack.request.#{status}"
|
62
|
+
end
|
63
|
+
|
43
64
|
self
|
44
65
|
end
|
45
66
|
|
67
|
+
def middleware(middleware, *args, &block)
|
68
|
+
@builder.use(middleware, *args, &block)
|
69
|
+
end
|
70
|
+
|
46
71
|
def call(env)
|
47
|
-
|
72
|
+
response = []
|
73
|
+
Notifications.instrument 'rack.request.all'.freeze, response: response do
|
74
|
+
response.push(*@app.call(env))
|
75
|
+
end
|
48
76
|
end
|
49
77
|
|
50
78
|
def layout(&block)
|
@@ -62,5 +90,6 @@ module Praxis
|
|
62
90
|
def config=(config)
|
63
91
|
@config.set(config)
|
64
92
|
end
|
93
|
+
|
65
94
|
end
|
66
95
|
end
|
data/lib/praxis/bootloader.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Praxis
|
2
2
|
|
3
|
-
|
4
3
|
class Bootloader
|
5
4
|
|
6
|
-
attr_reader :application
|
5
|
+
attr_reader :application
|
6
|
+
attr_reader :stages
|
7
7
|
|
8
8
|
def initialize(application)
|
9
9
|
@application = application
|
@@ -24,6 +24,9 @@ module Praxis
|
|
24
24
|
# Require environment first. they define constants and environment specific settings
|
25
25
|
stages << BootloaderStages::Environment.new(:environment, application)
|
26
26
|
|
27
|
+
# then setup plugins
|
28
|
+
stages << BootloaderStages::PluginLoader.new(:plugins, application)
|
29
|
+
|
27
30
|
# then the initializers. as it is their job to ensure monkey patches and other
|
28
31
|
# config is in place first.
|
29
32
|
stages << BootloaderStages::FileLoader.new(:initializers, application)
|
@@ -71,11 +74,41 @@ module Praxis
|
|
71
74
|
stages.find { |stage| stage.name == stage_name }.after(*stage_path, &block)
|
72
75
|
end
|
73
76
|
|
74
|
-
def use(plugin
|
75
|
-
|
77
|
+
def use(plugin,**options, &block)
|
78
|
+
if plugin.ancestors.include?(PluginConcern)
|
79
|
+
plugin.setup!
|
80
|
+
plugin = plugin::Plugin
|
81
|
+
end
|
82
|
+
|
83
|
+
instance = if plugin.ancestors.include?(Singleton)
|
84
|
+
plugin.instance
|
85
|
+
elsif plugin.kind_of?(Class)
|
86
|
+
plugin.new
|
87
|
+
else
|
88
|
+
plugin
|
89
|
+
end
|
90
|
+
|
91
|
+
instance.application = application
|
92
|
+
instance.options.merge!(options)
|
93
|
+
instance.block = block if block_given?
|
94
|
+
|
95
|
+
if application.plugins.key?(instance.config_key)
|
96
|
+
raise "Can not use plugin: #{plugin}, another plugin is already registered with key: #{instance.config_key}"
|
97
|
+
end
|
98
|
+
|
99
|
+
if instance.config_key.nil?
|
100
|
+
raise "Error initializing plugin: #{plugin}, config_key may not be nil."
|
101
|
+
end
|
102
|
+
|
103
|
+
application.plugins[instance.config_key] = instance
|
104
|
+
instance
|
76
105
|
end
|
77
106
|
|
78
107
|
def setup!
|
108
|
+
# use the Stats and Notifications plugins by default
|
109
|
+
use Praxis::Stats
|
110
|
+
use Praxis::Notifications
|
111
|
+
|
79
112
|
run
|
80
113
|
end
|
81
114
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Praxis
|
2
2
|
|
3
|
-
|
4
3
|
module BootloaderStages
|
5
4
|
|
6
5
|
class Environment < Stage
|
@@ -9,18 +8,14 @@ module Praxis
|
|
9
8
|
# 1) the environment.rb file - generic stuff for all environments
|
10
9
|
# 2) "Deployer.environment".rb - environment specific stuff
|
11
10
|
def execute
|
11
|
+
setup_initial_config!
|
12
|
+
|
12
13
|
env_file = application.root + "config/environment.rb"
|
13
14
|
require env_file if File.exists? env_file
|
14
15
|
|
15
|
-
application.plugins.each do |plugin|
|
16
|
-
plugin.setup!
|
17
|
-
end
|
18
|
-
|
19
16
|
unless application.file_layout
|
20
17
|
setup_default_layout!
|
21
18
|
end
|
22
|
-
|
23
|
-
setup_initial_config!
|
24
19
|
end
|
25
20
|
|
26
21
|
def setup_default_layout!
|
@@ -47,6 +42,7 @@ module Praxis
|
|
47
42
|
application.config do
|
48
43
|
attribute :praxis do
|
49
44
|
attribute :validate_responses, Attributor::Boolean, default: false
|
45
|
+
attribute :show_exceptions, Attributor::Boolean, default: false
|
50
46
|
end
|
51
47
|
end
|
52
48
|
end
|