praxis 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -2
- data/lib/api_browser/Gruntfile.js +6 -1
- data/lib/praxis.rb +2 -14
- data/lib/praxis/action_definition.rb +45 -16
- data/lib/praxis/api_definition.rb +36 -17
- data/lib/praxis/api_general_info.rb +59 -16
- data/lib/praxis/request_stages/request_stage.rb +2 -6
- data/lib/praxis/resource_definition.rb +50 -17
- data/lib/praxis/router.rb +10 -11
- data/lib/praxis/routing_config.rb +65 -0
- data/lib/praxis/tasks/routes.rb +8 -4
- data/lib/praxis/trait.rb +107 -0
- data/lib/praxis/types/media_type_common.rb +1 -1
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +1 -1
- data/spec/functional_spec.rb +16 -3
- data/spec/praxis/action_definition_spec.rb +107 -5
- data/spec/praxis/api_definition_spec.rb +67 -44
- data/spec/praxis/api_general_info_spec.rb +28 -14
- data/spec/praxis/media_type_spec.rb +33 -6
- data/spec/praxis/resource_definition_spec.rb +46 -12
- data/spec/praxis/router_spec.rb +9 -15
- data/spec/praxis/routing_config_spec.rb +89 -0
- data/spec/praxis/trait_spec.rb +38 -0
- data/spec/spec_app/app/controllers/instances.rb +6 -2
- data/spec/spec_app/design/resources/instances.rb +19 -10
- data/spec/spec_app/design/resources/volumes.rb +3 -3
- data/spec/support/spec_resource_definitions.rb +11 -6
- data/tasks/thor/example.rb +43 -35
- metadata +8 -6
- data/lib/praxis/skeletor/restful_routing_config.rb +0 -55
- data/spec/praxis/restful_routing_config_spec.rb +0 -101
data/tasks/thor/example.rb
CHANGED
@@ -4,10 +4,10 @@ module PraxisGen
|
|
4
4
|
include Thor::Actions
|
5
5
|
|
6
6
|
namespace "praxis:example"
|
7
|
-
|
7
|
+
|
8
8
|
argument :app_name, required: true
|
9
9
|
desc "new", "Generates a new 'hello world' example application under an <app_name> directory"
|
10
|
-
|
10
|
+
|
11
11
|
def new
|
12
12
|
puts "GENERATION COMMENCED!! (for #{app_name})"
|
13
13
|
# Fix weird symbols in the app name (if they are)
|
@@ -33,12 +33,18 @@ module PraxisGen
|
|
33
33
|
puts " bundle exec rackup"
|
34
34
|
puts
|
35
35
|
puts " # terminal 2:"
|
36
|
-
puts "
|
37
|
-
puts " curl -i http://localhost:8888/api/hello
|
38
|
-
puts "
|
36
|
+
puts " # Index: list the hello words (especifying api version through the query string) "
|
37
|
+
puts " curl -i 'http://localhost:8888/api/hello?api_version=1.0' -H 'Authorization: Bearer XYZ' "
|
38
|
+
puts ""
|
39
|
+
puts " # Show: list one of the hello words (especifying api version through a header) "
|
40
|
+
puts " curl -i 'http://localhost:8888/api/hello/1' -H 'X-Api-Version: 1.0' -H 'Authorization: Bearer XYZ'"
|
41
|
+
puts ""
|
42
|
+
puts " # NotFound: Hello word will not be found under API 2.0"
|
43
|
+
puts " curl -i 'http://localhost:8888/api/hello/1' -H 'X-Api-Version: 2.0' -H 'Authorization: Bearer XYZ'"
|
44
|
+
puts " #Note: The Authorization header is made required in the application to emulate OAuth2 (but not used)"
|
39
45
|
nil
|
40
46
|
end
|
41
|
-
private
|
47
|
+
private
|
42
48
|
# Returns relative path for the new application
|
43
49
|
#
|
44
50
|
# @return [String]
|
@@ -51,8 +57,8 @@ private
|
|
51
57
|
def app_dir_pathname
|
52
58
|
@app_dir_pathname ||= Pathname.new(app_name)
|
53
59
|
end
|
54
|
-
|
55
|
-
|
60
|
+
|
61
|
+
|
56
62
|
# Returns path string built from the set of the given strings
|
57
63
|
#
|
58
64
|
# @param [String,Array] strings
|
@@ -65,8 +71,8 @@ private
|
|
65
71
|
def path(*strings)
|
66
72
|
app_dir_pathname.join(*strings).to_s
|
67
73
|
end
|
68
|
-
|
69
|
-
|
74
|
+
|
75
|
+
|
70
76
|
# Creates './config/environment.rb' file
|
71
77
|
#
|
72
78
|
# @return [void]
|
@@ -100,8 +106,8 @@ RUBY
|
|
100
106
|
end
|
101
107
|
nil
|
102
108
|
end
|
103
|
-
|
104
|
-
|
109
|
+
|
110
|
+
|
105
111
|
# Creates './Gemfile' file
|
106
112
|
#
|
107
113
|
# @return [void]
|
@@ -122,8 +128,8 @@ RUBY
|
|
122
128
|
end
|
123
129
|
nil
|
124
130
|
end
|
125
|
-
|
126
|
-
|
131
|
+
|
132
|
+
|
127
133
|
# Creates './Rakefile' file
|
128
134
|
#
|
129
135
|
# @return [void]
|
@@ -137,8 +143,8 @@ RUBY
|
|
137
143
|
end
|
138
144
|
nil
|
139
145
|
end
|
140
|
-
|
141
|
-
|
146
|
+
|
147
|
+
|
142
148
|
# Creates './config.ru' file
|
143
149
|
#
|
144
150
|
# @return [void]
|
@@ -160,8 +166,8 @@ RUBY
|
|
160
166
|
end
|
161
167
|
nil
|
162
168
|
end
|
163
|
-
|
164
|
-
|
169
|
+
|
170
|
+
|
165
171
|
def generate_app_definitions_hello_world
|
166
172
|
create_file path('design/api.rb') do
|
167
173
|
<<-RUBY
|
@@ -173,15 +179,16 @@ RUBY
|
|
173
179
|
# media_type media_type
|
174
180
|
# end
|
175
181
|
Praxis::ApiDefinition.define do
|
176
|
-
|
182
|
+
# Trait that when included will require a Bearer authorization header to be passed in.
|
183
|
+
trait :authorized do
|
177
184
|
headers do
|
178
|
-
key "
|
185
|
+
key "Authorization", String, regexp: /^.*Bearer\s/, required: true
|
179
186
|
end
|
180
187
|
end
|
181
188
|
end
|
182
189
|
RUBY
|
183
190
|
end
|
184
|
-
|
191
|
+
|
185
192
|
create_file path('design/resources/hello.rb') do
|
186
193
|
<<-RUBY
|
187
194
|
module V1
|
@@ -192,21 +199,23 @@ module V1
|
|
192
199
|
media_type V1::MediaTypes::Hello
|
193
200
|
version '1.0'
|
194
201
|
|
195
|
-
|
196
|
-
|
202
|
+
prefix '/api/hello'
|
203
|
+
|
204
|
+
# Will apply to all actions of this resource
|
205
|
+
trait :authorized
|
206
|
+
|
207
|
+
action_defaults do
|
208
|
+
response :ok
|
197
209
|
end
|
198
210
|
|
199
211
|
action :index do
|
200
|
-
use :versionable
|
201
212
|
|
202
213
|
routing do
|
203
214
|
get ''
|
204
215
|
end
|
205
|
-
response :ok
|
206
216
|
end
|
207
217
|
|
208
218
|
action :show do
|
209
|
-
use :versionable
|
210
219
|
|
211
220
|
routing do
|
212
221
|
get '/:id'
|
@@ -214,7 +223,6 @@ module V1
|
|
214
223
|
params do
|
215
224
|
attribute :id, Integer, required: true, min: 0
|
216
225
|
end
|
217
|
-
response :ok
|
218
226
|
response :not_found
|
219
227
|
end
|
220
228
|
end
|
@@ -222,19 +230,19 @@ module V1
|
|
222
230
|
end
|
223
231
|
RUBY
|
224
232
|
end
|
225
|
-
|
233
|
+
|
226
234
|
create_file path('design/media_types/hello.rb') do
|
227
235
|
<<-RUBY
|
228
236
|
module V1
|
229
237
|
module MediaTypes
|
230
238
|
class Hello < Praxis::MediaType
|
231
|
-
|
239
|
+
|
232
240
|
identifier 'application/json'
|
233
|
-
|
241
|
+
|
234
242
|
attributes do
|
235
243
|
attribute :string, String
|
236
244
|
end
|
237
|
-
|
245
|
+
|
238
246
|
view :default do
|
239
247
|
attribute :string
|
240
248
|
end
|
@@ -244,8 +252,8 @@ RUBY
|
|
244
252
|
RUBY
|
245
253
|
end
|
246
254
|
end
|
247
|
-
|
248
|
-
|
255
|
+
|
256
|
+
|
249
257
|
def generate_app_controllers_hello_world
|
250
258
|
create_file path('app/controllers/hello.rb') do
|
251
259
|
<<-RUBY
|
@@ -268,7 +276,7 @@ module V1
|
|
268
276
|
if hello
|
269
277
|
response.body = { id: id, data: hello }
|
270
278
|
else
|
271
|
-
self.response = Praxis::Responses::NotFound.new
|
279
|
+
self.response = Praxis::Responses::NotFound.new(body: "Hello word with index \#{id} not found in our DB")
|
272
280
|
end
|
273
281
|
response.headers['Content-Type'] = 'application/json'
|
274
282
|
response
|
@@ -278,6 +286,6 @@ end
|
|
278
286
|
RUBY
|
279
287
|
end
|
280
288
|
end
|
281
|
-
|
289
|
+
|
282
290
|
end
|
283
291
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: praxis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep M. Blanquer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-04-
|
12
|
+
date: 2015-04-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -73,14 +73,14 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '3.
|
76
|
+
version: '3.4'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '3.
|
83
|
+
version: '3.4'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: praxis-blueprints
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -878,8 +878,8 @@ files:
|
|
878
878
|
- lib/praxis/restful_doc_generator.rb
|
879
879
|
- lib/praxis/route.rb
|
880
880
|
- lib/praxis/router.rb
|
881
|
+
- lib/praxis/routing_config.rb
|
881
882
|
- lib/praxis/simple_media_type.rb
|
882
|
-
- lib/praxis/skeletor/restful_routing_config.rb
|
883
883
|
- lib/praxis/stage.rb
|
884
884
|
- lib/praxis/stats.rb
|
885
885
|
- lib/praxis/tasks.rb
|
@@ -887,6 +887,7 @@ files:
|
|
887
887
|
- lib/praxis/tasks/console.rb
|
888
888
|
- lib/praxis/tasks/environment.rb
|
889
889
|
- lib/praxis/tasks/routes.rb
|
890
|
+
- lib/praxis/trait.rb
|
890
891
|
- lib/praxis/types/media_type_common.rb
|
891
892
|
- lib/praxis/types/multipart.rb
|
892
893
|
- lib/praxis/version.rb
|
@@ -924,11 +925,12 @@ files:
|
|
924
925
|
- spec/praxis/response_spec.rb
|
925
926
|
- spec/praxis/responses/internal_server_error_spec.rb
|
926
927
|
- spec/praxis/responses/validation_error_spec.rb
|
927
|
-
- spec/praxis/restful_routing_config_spec.rb
|
928
928
|
- spec/praxis/route_spec.rb
|
929
929
|
- spec/praxis/router_spec.rb
|
930
|
+
- spec/praxis/routing_config_spec.rb
|
930
931
|
- spec/praxis/stage_spec.rb
|
931
932
|
- spec/praxis/stats_spec.rb
|
933
|
+
- spec/praxis/trait_spec.rb
|
932
934
|
- spec/praxis/types/collection_spec.rb
|
933
935
|
- spec/praxis/types/multipart_spec.rb
|
934
936
|
- spec/spec_app/app/concerns/authenticated.rb
|
@@ -1,55 +0,0 @@
|
|
1
|
-
module Praxis
|
2
|
-
module Skeletor
|
3
|
-
class RestfulRoutingConfig
|
4
|
-
|
5
|
-
attr_reader :name, :resource_definition, :routes
|
6
|
-
|
7
|
-
def initialize(name, resource_definition, &block)
|
8
|
-
@name = name
|
9
|
-
@resource_definition = resource_definition
|
10
|
-
@routes = []
|
11
|
-
|
12
|
-
@version_prefix = ""
|
13
|
-
if resource_definition.version_options
|
14
|
-
version_using = Array(resource_definition.version_options[:using])
|
15
|
-
if version_using.include?(:path)
|
16
|
-
@version_prefix = "#{Praxis::Request::path_version_prefix}#{resource_definition.version}"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
prefix( "/" + resource_definition.name.split("::").last.underscore )
|
20
|
-
|
21
|
-
if resource_definition.routing_config
|
22
|
-
instance_eval(&resource_definition.routing_config)
|
23
|
-
end
|
24
|
-
|
25
|
-
instance_eval(&block)
|
26
|
-
end
|
27
|
-
|
28
|
-
def prefix(prefix=nil)
|
29
|
-
@path_prefix = prefix if prefix
|
30
|
-
@version_prefix + @path_prefix
|
31
|
-
end
|
32
|
-
|
33
|
-
def options(path, opts={}) add_route 'OPTIONS', path, opts end
|
34
|
-
def get(path, opts={}) add_route 'GET', path, opts end
|
35
|
-
def head(path, opts={}) add_route 'HEAD', path, opts end
|
36
|
-
def post(path, opts={}) add_route 'POST', path, opts end
|
37
|
-
def put(path, opts={}) add_route 'PUT', path, opts end
|
38
|
-
def delete(path, opts={}) add_route 'DELETE', path, opts end
|
39
|
-
def trace(path, opts={}) add_route 'TRACE', path, opts end
|
40
|
-
def connect(path, opts={}) add_route 'CONNECT', path, opts end
|
41
|
-
def patch(path, opts={}) add_route 'PATCH', path, opts end
|
42
|
-
def any(path, opts={}) add_route 'ANY', path, opts end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
def add_route(verb, path, options={})
|
47
|
-
path = Mustermann.new(prefix + path)
|
48
|
-
|
49
|
-
@routes << Route.new(verb, path, resource_definition.version, **options)
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
@@ -1,101 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Praxis::Skeletor::RestfulRoutingConfig do
|
4
|
-
|
5
|
-
let(:resource_definition) do
|
6
|
-
Class.new do
|
7
|
-
include Praxis::ResourceDefinition
|
8
|
-
def self.name; 'MyResource'; end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
let(:action_name) { :index }
|
13
|
-
let(:routing_block) { Proc.new{} }
|
14
|
-
let(:default_route_prefix) { "/" + resource_definition.name.split("::").last.underscore }
|
15
|
-
|
16
|
-
subject(:routing_config){ Praxis::Skeletor::RestfulRoutingConfig.new(action_name, resource_definition, &routing_block) }
|
17
|
-
|
18
|
-
context "#initialize" do
|
19
|
-
it "name" do
|
20
|
-
expect(subject.name).to eq(:index)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "resource_definition" do
|
24
|
-
expect(subject.resource_definition).to eq(resource_definition)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "routes" do
|
28
|
-
expect(subject.routes.empty?).to eq(true)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "prefix without path version" do
|
32
|
-
expect(subject.prefix).to eq(default_route_prefix)
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'prefix using path version' do
|
36
|
-
let(:resource_definition) do
|
37
|
-
Class.new do
|
38
|
-
include Praxis::ResourceDefinition
|
39
|
-
version "1.0", using: :path
|
40
|
-
def self.name; 'MyVersionedResource'; end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
it "prefix" do
|
44
|
-
expect(subject.prefix).to eq("/v1.0#{default_route_prefix}")
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context "#add_route" do
|
50
|
-
let(:route_verb){ 'GET' }
|
51
|
-
let(:route_path){ '/path' }
|
52
|
-
let(:route_opts){ {option: 1} }
|
53
|
-
|
54
|
-
before(:each) do
|
55
|
-
routing_config.add_route(route_verb, route_path, route_opts)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "routes" do
|
59
|
-
expect(subject.routes.length).to eq(1)
|
60
|
-
end
|
61
|
-
|
62
|
-
it "saves the verb and options into the route" do
|
63
|
-
route = subject.routes.first
|
64
|
-
|
65
|
-
expect(route.verb).to eq(route_verb)
|
66
|
-
expect(route.options).to eq(route_opts)
|
67
|
-
end
|
68
|
-
|
69
|
-
context "with a resource definition that does not have a route prefix" do
|
70
|
-
it 'saves the path with the default path prefix' do
|
71
|
-
path = subject.routes.first.path.to_s
|
72
|
-
expect(path).to eq(default_route_prefix + route_path)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
context "with a resource definition that has a route prefix" do
|
77
|
-
let(:routing_block) { Proc.new{ prefix "/my_custom_route" } }
|
78
|
-
subject(:routing_config){ Praxis::Skeletor::RestfulRoutingConfig.new(action_name, resource_definition, &routing_block) }
|
79
|
-
it 'appends the prefix to the path' do
|
80
|
-
path = subject.routes.first.path.to_s
|
81
|
-
expect(path).to eq("/my_custom_route" + route_path)
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'route helpers' do
|
88
|
-
let(:route_prefix) { nil }
|
89
|
-
|
90
|
-
it 'call the add_route with the correct parameters' do
|
91
|
-
helper_verbs = [:get, :put, :post, :delete, :head, :options, :patch, :any]
|
92
|
-
helper_verbs.each do |verb|
|
93
|
-
path = "/path_for_#{verb}"
|
94
|
-
options = {option: verb}
|
95
|
-
expect(subject).to receive(:add_route).with(verb.to_s.upcase,path,options)
|
96
|
-
subject.__send__(verb, path, options)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|