traxis 0.0.1 → 0.0.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.
- checksums.yaml +4 -4
- data/Guardfile +39 -0
- data/lib/traxis.rb +1 -1
- data/lib/traxis/controller_helpers.rb +49 -9
- data/lib/traxis/responses.rb +6 -0
- data/lib/traxis/version.rb +1 -1
- data/spec/helpers/base.rb +39 -0
- data/spec/spec_app/app/controllers/instances.rb +63 -0
- data/spec/spec_app/app/responses/bulk_response.rb +6 -0
- data/spec/spec_app/app/responses/multipart.rb +10 -0
- data/spec/spec_app/app/responses/other_response.rb +6 -0
- data/spec/spec_app/config.ru +17 -0
- data/spec/spec_app/config/environment.rb +17 -0
- data/spec/spec_app/design/api.rb +27 -0
- data/spec/spec_app/design/media_types/instance.rb +35 -0
- data/spec/spec_app/design/media_types/volume.rb +34 -0
- data/spec/spec_app/design/media_types/volume_snapshot.rb +38 -0
- data/spec/spec_app/design/resources/instances.rb +161 -0
- data/spec/spec_helper.rb +16 -1
- data/spec/support/people_controller.rb +1 -1
- data/spec/test.db +0 -0
- data/spec/traxis/controller_helpers_spec.rb +17 -0
- data/traxis.gemspec +2 -0
- metadata +144 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ea7579c74448c0827a9cfb517bc240c567359fd
|
4
|
+
data.tar.gz: 244e0afec718abd21f91b8f15323487940bb5bc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3960987c46f5e77f0013283a9d5980503f4e5ad2daffbcfbb5b1c22a70d0f73fa2825bc452c21192f18219e80bbc0c2cc23c588af4704f6795ca26587ab1ca93
|
7
|
+
data.tar.gz: 5faacbb77463f0d8dbb75f3ce4579709cc99a734daa906b25168cd5264dbdd8eaf0f2461c670c235de6f2e28591dca97920303e9c106edc708d1baffb61c071c
|
data/Guardfile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :bundler do
|
5
|
+
watch('Gemfile')
|
6
|
+
# Uncomment next line if your Gemfile contains the `gemspec' command.
|
7
|
+
# watch(/^.+\.gemspec/)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
11
|
+
# rspec may be run, below are examples of the most common uses.
|
12
|
+
# * bundler: 'bundle exec rspec'
|
13
|
+
# * bundler binstubs: 'bin/rspec'
|
14
|
+
# * spring: 'bin/rsspec' (This will use spring if running and you have
|
15
|
+
# installed the spring binstubs per the docs)
|
16
|
+
# * zeus: 'zeus rspec' (requires the server to be started separetly)
|
17
|
+
# * 'just' rspec: 'rspec'
|
18
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
19
|
+
watch(%r{^spec/.+_spec\.rb$})
|
20
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
21
|
+
watch('spec/spec_helper.rb') { "spec" }
|
22
|
+
|
23
|
+
# Rails example
|
24
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
25
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
26
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
27
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
28
|
+
watch('config/routes.rb') { "spec/routing" }
|
29
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
30
|
+
watch('spec/rails_helper.rb') { "spec" }
|
31
|
+
|
32
|
+
# Capybara features specs
|
33
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
34
|
+
|
35
|
+
# Turnip features and steps
|
36
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
37
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
38
|
+
end
|
39
|
+
|
data/lib/traxis.rb
CHANGED
@@ -3,7 +3,13 @@ module Traxis
|
|
3
3
|
protected
|
4
4
|
|
5
5
|
def association_chain
|
6
|
-
@association_chain ||=
|
6
|
+
@association_chain ||= begin
|
7
|
+
if begin_of_association_chain.kind_of?(::ActiveRecord::Relation)
|
8
|
+
begin_of_association_chain.all
|
9
|
+
else
|
10
|
+
begin_of_association_chain
|
11
|
+
end
|
12
|
+
end
|
7
13
|
end
|
8
14
|
|
9
15
|
def assign_object_attributes(object, attribute_hash)
|
@@ -18,8 +24,29 @@ module Traxis
|
|
18
24
|
self.class.resource_options[:class]
|
19
25
|
end
|
20
26
|
|
27
|
+
def build_resource
|
28
|
+
if association_chain != resource_class
|
29
|
+
association_chain.__send__(collection_relation_name).new(payload_attributes)
|
30
|
+
else
|
31
|
+
association_chain.new(payload_attributes)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
### If begin of association chain is an instance of ar model, i.e. current_user
|
37
|
+
### send the collection relation name, i.e. current_user.posts.all
|
21
38
|
def collection
|
22
|
-
@collection ||=
|
39
|
+
@collection ||= begin
|
40
|
+
unless begin_of_association_chain.respond_to?(:all)
|
41
|
+
association_chain.__send__(collection_relation_name).all
|
42
|
+
else
|
43
|
+
association_chain.all
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection_relation_name
|
49
|
+
@collection_relation_name ||= resource_class.name.demodulize.underscore.pluralize
|
23
50
|
end
|
24
51
|
|
25
52
|
def collection_serializer_class
|
@@ -30,6 +57,14 @@ module Traxis
|
|
30
57
|
save_resource
|
31
58
|
end
|
32
59
|
|
60
|
+
def end_of_association_chain
|
61
|
+
:all
|
62
|
+
end
|
63
|
+
|
64
|
+
def method_for_find
|
65
|
+
resource_options[:finder]
|
66
|
+
end
|
67
|
+
|
33
68
|
def params
|
34
69
|
@params ||= request.params.attributes
|
35
70
|
end
|
@@ -45,21 +80,24 @@ module Traxis
|
|
45
80
|
def resource
|
46
81
|
@resource ||= begin
|
47
82
|
if request.action.name == :create
|
48
|
-
|
83
|
+
build_resource
|
49
84
|
elsif request.action.name == :update
|
50
85
|
assign_object_attributes(resource_query_result, payload_attributes)
|
51
86
|
else
|
52
|
-
|
87
|
+
resource_query_result
|
53
88
|
end
|
54
89
|
end
|
55
90
|
end
|
56
91
|
|
57
|
-
def resource_finder
|
58
|
-
:find
|
59
|
-
end
|
60
|
-
|
61
92
|
def resource_query_result
|
62
|
-
@resource_query_result ||=
|
93
|
+
@resource_query_result ||= begin
|
94
|
+
unless association_chain.respond_to?(method_for_find)
|
95
|
+
association_chain.__send__(collection_relation_name)
|
96
|
+
.__send__(method_for_find, params[resource_options[:finder_param]])
|
97
|
+
else
|
98
|
+
association_chain.__send__(method_for_find, params[resource_options[:finder_param]])
|
99
|
+
end
|
100
|
+
end
|
63
101
|
end
|
64
102
|
|
65
103
|
def serialized_collection
|
@@ -81,6 +119,8 @@ module Traxis
|
|
81
119
|
request.query.map do |k,v|
|
82
120
|
collection.__send__("#{k}", *v)
|
83
121
|
end
|
122
|
+
|
123
|
+
collection.__send__(end_of_association_chain)
|
84
124
|
end
|
85
125
|
end
|
86
126
|
|
data/lib/traxis/responses.rb
CHANGED
@@ -3,6 +3,12 @@ module Traxis
|
|
3
3
|
class Base < ::Praxis::Response
|
4
4
|
end
|
5
5
|
|
6
|
+
class Ok < ::Traxis::Responses::Base
|
7
|
+
include ::Traxis::Response::JSON
|
8
|
+
|
9
|
+
self.status = 200
|
10
|
+
end
|
11
|
+
|
6
12
|
class Unauthorized < ::Traxis::Responses::Base
|
7
13
|
include ::Traxis::Response::JSON
|
8
14
|
include ::Traxis::Response::Meta
|
data/lib/traxis/version.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Helpers
|
2
|
+
def fake_rack_input
|
3
|
+
StringIO.new('something=given')
|
4
|
+
end
|
5
|
+
|
6
|
+
def fake_env
|
7
|
+
env = Rack::MockRequest.env_for('/people')
|
8
|
+
env['rack.input'] = fake_rack_input
|
9
|
+
env['CONTENT_TYPE'] = 'application/json'
|
10
|
+
env['HTTP_VERSION'] = 'HTTP/1.1'
|
11
|
+
env
|
12
|
+
end
|
13
|
+
|
14
|
+
def fake_context
|
15
|
+
{
|
16
|
+
params: [Attributor::AttributeResolver::ROOT_PREFIX, "params".freeze],
|
17
|
+
headers: [Attributor::AttributeResolver::ROOT_PREFIX, "headers".freeze],
|
18
|
+
payload: [Attributor::AttributeResolver::Data, "payload".freeze]
|
19
|
+
}.freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def fake_request
|
23
|
+
request = Praxis::Request.new(fake_env)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fake_request_with_payload
|
27
|
+
fake_request.payload = fake_payload_attributes
|
28
|
+
end
|
29
|
+
|
30
|
+
def fake_payload_attributes
|
31
|
+
::Attributor::Struct.new({
|
32
|
+
'name' => "Jason"
|
33
|
+
})
|
34
|
+
end
|
35
|
+
|
36
|
+
def fake_rack_input_hash
|
37
|
+
StringIO.new(fake_payload_attributes.to_json)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Instances
|
2
|
+
include Praxis::Controller
|
3
|
+
|
4
|
+
implements ApiResources::Instances
|
5
|
+
|
6
|
+
before :validate, actions: [:index] do |controller|
|
7
|
+
#p [:before, :validate, :params_and_headers, controller.request.action.name]
|
8
|
+
end
|
9
|
+
|
10
|
+
before actions: [:show] do
|
11
|
+
#puts "before action"
|
12
|
+
end
|
13
|
+
|
14
|
+
def index(response_content_type:, **params)
|
15
|
+
response.headers['Content-Type'] = response_content_type #'application/vnd.acme.instance;type=collection'
|
16
|
+
JSON.generate(params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def show(cloud_id:, id:, junk:, **other_params)
|
20
|
+
payload = request.payload
|
21
|
+
response.body = {cloud_id: cloud_id, id: id, junk: junk, other_params: other_params, payload: payload.dump}
|
22
|
+
response.headers['Content-Type'] = 'application/vnd.acme.instance'
|
23
|
+
response
|
24
|
+
end
|
25
|
+
|
26
|
+
def bulk_create(cloud_id:)
|
27
|
+
self.response = BulkResponse.new
|
28
|
+
|
29
|
+
request.payload.each do |instance_id,instance|
|
30
|
+
part_body = JSON.pretty_generate(key: instance_id, value: instance.render(:create))
|
31
|
+
headers = {
|
32
|
+
'Status' => '201',
|
33
|
+
'Content-Type' => Instance.identifier,
|
34
|
+
'Location' => self.class.action(:show).primary_route.path.expand(cloud_id: cloud_id, id: instance.id)
|
35
|
+
}
|
36
|
+
|
37
|
+
part = Praxis::MultipartPart.new(part_body, headers)
|
38
|
+
|
39
|
+
response.add_part(instance_id, part)
|
40
|
+
end
|
41
|
+
|
42
|
+
response
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def attach_file(id:, cloud_id:)
|
47
|
+
response.headers['Content-Type'] = 'application/json'
|
48
|
+
|
49
|
+
destination_path = request.payload['destination_path']
|
50
|
+
file = request.payload['file']
|
51
|
+
|
52
|
+
result = {
|
53
|
+
destination_path: destination_path,
|
54
|
+
file: file.dump
|
55
|
+
}
|
56
|
+
|
57
|
+
response.body = JSON.pretty_generate(result)
|
58
|
+
|
59
|
+
response
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Praxis::Application.configure do |application|
|
2
|
+
application.layout do
|
3
|
+
layout do
|
4
|
+
map :initializers, 'config/initializers/**/*'
|
5
|
+
map :design, 'design/' do
|
6
|
+
map :api, 'api.rb'
|
7
|
+
map :media_types, '**/media_types/**/*'
|
8
|
+
map :resources, '**/resources/**/*'
|
9
|
+
end
|
10
|
+
map :app, 'app/' do
|
11
|
+
map :models, 'models/**/*'
|
12
|
+
map :controllers, '**/controllers/**/*'
|
13
|
+
map :responses, '**/responses/**/*'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Praxis::ApiDefinition.define do
|
2
|
+
|
3
|
+
response_template :other_response do |media_type:|
|
4
|
+
status 200
|
5
|
+
media_type media_type
|
6
|
+
end
|
7
|
+
|
8
|
+
response_template :multipart do
|
9
|
+
status 200
|
10
|
+
media_type 'multipart/form-data'
|
11
|
+
end
|
12
|
+
|
13
|
+
response_template :bulk_response do |media_type:, parts: |
|
14
|
+
status 200
|
15
|
+
media_type 'multipart/form-data'
|
16
|
+
|
17
|
+
parts[:media_type] ||= media_type if parts.kind_of? Hash
|
18
|
+
parts(parts)
|
19
|
+
end
|
20
|
+
|
21
|
+
trait :authenticated do
|
22
|
+
headers do
|
23
|
+
header :host
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Instance < Praxis::MediaType
|
2
|
+
|
3
|
+
identifier 'application/vnd.acme.instance'
|
4
|
+
|
5
|
+
attributes do
|
6
|
+
attribute :id, Integer
|
7
|
+
attribute :name, String, example: /[:first_name:]/
|
8
|
+
|
9
|
+
attribute :href, String
|
10
|
+
|
11
|
+
attribute :root_volume, Volume
|
12
|
+
|
13
|
+
links do
|
14
|
+
link :root_volume
|
15
|
+
link :other_volume, Volume, using: :data_volume
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
view :default do
|
20
|
+
attribute :id
|
21
|
+
attribute :root_volume
|
22
|
+
attribute :links
|
23
|
+
end
|
24
|
+
|
25
|
+
view :link do
|
26
|
+
attribute :id
|
27
|
+
attribute :href
|
28
|
+
end
|
29
|
+
|
30
|
+
view :create do
|
31
|
+
attribute :id
|
32
|
+
attribute :name
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Volume < Praxis::MediaType
|
2
|
+
identifier 'application/json'
|
3
|
+
|
4
|
+
attributes do
|
5
|
+
attribute :id, Integer
|
6
|
+
attribute :name, String
|
7
|
+
|
8
|
+
attribute :source, VolumeSnapshot
|
9
|
+
|
10
|
+
# returns VolumeSnapshot::Collection if exists
|
11
|
+
attribute :snapshots, Praxis::Collection.of(VolumeSnapshot)
|
12
|
+
|
13
|
+
links do
|
14
|
+
link :source
|
15
|
+
link :snapshots
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
view :default do
|
21
|
+
attribute :id
|
22
|
+
attribute :name
|
23
|
+
attribute :source
|
24
|
+
attribute :snapshots
|
25
|
+
attribute :links
|
26
|
+
end
|
27
|
+
|
28
|
+
view :link do
|
29
|
+
attribute :id
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class VolumeSnapshot < Praxis::MediaType
|
2
|
+
identifier 'application/json'
|
3
|
+
|
4
|
+
attributes do
|
5
|
+
attribute :id, Integer
|
6
|
+
attribute :name, String, regexp: /snapshot-(\w+)/
|
7
|
+
end
|
8
|
+
|
9
|
+
view :default do
|
10
|
+
attribute :id
|
11
|
+
attribute :name
|
12
|
+
end
|
13
|
+
|
14
|
+
view :link do
|
15
|
+
attribute :id
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
class Collection < Praxis::MediaTypeCollection
|
20
|
+
identifier 'application/json+collection'
|
21
|
+
|
22
|
+
member_type VolumeSnapshot
|
23
|
+
|
24
|
+
attributes do
|
25
|
+
attribute :name, String, regexp: /snapshots-(\w+)/
|
26
|
+
attribute :size, Integer, example: proc { |collection| collection.to_a.count }
|
27
|
+
attribute :href, String
|
28
|
+
end
|
29
|
+
|
30
|
+
view :link do
|
31
|
+
attribute :name
|
32
|
+
attribute :size
|
33
|
+
attribute :href
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module ApiResources
|
2
|
+
class Instances
|
3
|
+
include Praxis::ResourceDefinition
|
4
|
+
|
5
|
+
media_type Instance
|
6
|
+
version '1.0'
|
7
|
+
|
8
|
+
#response_groups :premium
|
9
|
+
#responses :instance_limit_reached
|
10
|
+
#responses :pay_us_money
|
11
|
+
#response :create, location: /instances/
|
12
|
+
|
13
|
+
use :authenticated
|
14
|
+
|
15
|
+
routing do
|
16
|
+
prefix '/clouds/:cloud_id/instances'
|
17
|
+
end
|
18
|
+
|
19
|
+
params do
|
20
|
+
attribute :cloud_id, Integer, required: true
|
21
|
+
end
|
22
|
+
|
23
|
+
action :index do
|
24
|
+
routing do
|
25
|
+
get ''
|
26
|
+
end
|
27
|
+
|
28
|
+
response_content_type = self.resource_definition.media_type.identifier + ";type=collection"
|
29
|
+
params do
|
30
|
+
attribute :response_content_type, String, default: response_content_type
|
31
|
+
end
|
32
|
+
|
33
|
+
response :ok, media_type: response_content_type
|
34
|
+
end
|
35
|
+
|
36
|
+
action :show do
|
37
|
+
routing do
|
38
|
+
get '/:id'
|
39
|
+
get '/something/:id', name: :alternate
|
40
|
+
end
|
41
|
+
|
42
|
+
response :ok
|
43
|
+
|
44
|
+
params do
|
45
|
+
attribute :id
|
46
|
+
attribute :junk, String, default: ''
|
47
|
+
attribute :some_date, DateTime, default: DateTime.parse('2012-12-21')
|
48
|
+
end
|
49
|
+
payload do
|
50
|
+
attribute :something, String
|
51
|
+
attribute :optional, String, default: "not given"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
action :bulk_create do
|
57
|
+
routing do
|
58
|
+
post ''
|
59
|
+
end
|
60
|
+
|
61
|
+
payload Praxis::Multipart.of(key: Integer, value: Instance)
|
62
|
+
|
63
|
+
# Using a hash param for parts
|
64
|
+
response :bulk_response ,
|
65
|
+
parts: {
|
66
|
+
like: :created,
|
67
|
+
media_type: Instance # Could be left blank and will inherit
|
68
|
+
}
|
69
|
+
|
70
|
+
# Using a block for parts to defin a sub-request
|
71
|
+
# sub_request = proc do
|
72
|
+
# status 201
|
73
|
+
# media_type Instance
|
74
|
+
# headers ['X-Foo','X-Bar']
|
75
|
+
# end
|
76
|
+
# response :bulk_response, parts: sub_request
|
77
|
+
|
78
|
+
|
79
|
+
# multi 200, H1
|
80
|
+
# parts_as :resp1
|
81
|
+
|
82
|
+
# part_type do
|
83
|
+
# 201
|
84
|
+
# h Location ~= /asdfa/
|
85
|
+
# end
|
86
|
+
|
87
|
+
# part 'dest_dir' do
|
88
|
+
|
89
|
+
# end
|
90
|
+
# part 'file' do
|
91
|
+
# mt binary
|
92
|
+
# end
|
93
|
+
end
|
94
|
+
|
95
|
+
#action :get_user_data do
|
96
|
+
# response :get_user_data do
|
97
|
+
# media_type: UserData
|
98
|
+
# end
|
99
|
+
#end
|
100
|
+
|
101
|
+
action :attach_file do
|
102
|
+
routing do
|
103
|
+
post '/:id/files'
|
104
|
+
end
|
105
|
+
|
106
|
+
params do
|
107
|
+
attribute :id
|
108
|
+
end
|
109
|
+
|
110
|
+
payload Praxis::Multipart do
|
111
|
+
key 'destination_path', String, required: true
|
112
|
+
key 'file', Attributor::FileUpload, required: true
|
113
|
+
end
|
114
|
+
|
115
|
+
response :ok, media_type: 'application/json'
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# OTHER USAGES:
|
120
|
+
# note: these are all hypothetical, pending, brainstorming usages.
|
121
|
+
|
122
|
+
# given: single file, super simple upload, with count constraint
|
123
|
+
# result: only one part is accepted
|
124
|
+
# example:
|
125
|
+
# payload Praxis::Multipart.of(FileUpload), count: 1
|
126
|
+
|
127
|
+
# given: multiple file uploads
|
128
|
+
# example:
|
129
|
+
# payload Praxis::Multipart.of(key: UUID, value: Attributor::FileUpload)
|
130
|
+
|
131
|
+
# given: any untyped multipart request body
|
132
|
+
# example:
|
133
|
+
# payload Praxis::Multipart
|
134
|
+
|
135
|
+
# given: single known key, plus multiple uploaded files which can take any name
|
136
|
+
# result: multiple files collected into a single Hash.of(value: FileUpload)
|
137
|
+
# example:
|
138
|
+
# payload Praxis::Multipart do
|
139
|
+
# key 'destination', String, required: true
|
140
|
+
# splat 'remaining', Hash.of(value: FileUpload)
|
141
|
+
# end
|
142
|
+
|
143
|
+
# given: single known key, plus multiple uploaded files which can take any name
|
144
|
+
# result: file parts coerced to FileUpload
|
145
|
+
# example:
|
146
|
+
# payload Praxis::Multipart do
|
147
|
+
# key 'destination', String, required: true
|
148
|
+
# other_keys FileUpload
|
149
|
+
# end
|
150
|
+
|
151
|
+
# given: single known key, plus multiple uploaded files, with names like 'file-'
|
152
|
+
# result: file parts coerced to FileUpload
|
153
|
+
# example:
|
154
|
+
# payload Praxis::Multipart do
|
155
|
+
# key 'destination', String, required: true
|
156
|
+
# match /file-.+/, FileUpload
|
157
|
+
# end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,12 +8,27 @@ Bundler.setup :default, :test
|
|
8
8
|
require 'simplecov'
|
9
9
|
|
10
10
|
require 'praxis'
|
11
|
-
|
11
|
+
|
12
12
|
require 'rack/test'
|
13
13
|
require 'rspec/its'
|
14
14
|
require 'rspec/collection_matchers'
|
15
15
|
require 'pry'
|
16
16
|
|
17
|
+
require 'praxis'
|
18
|
+
require 'helpers/base'
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.include Rack::Test::Methods
|
22
|
+
config.include Helpers
|
23
|
+
config.before(:suite) do
|
24
|
+
Praxis::Blueprint.caching_enabled = true
|
25
|
+
Praxis::Application.instance.setup(root:'spec/spec_app')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'traxis'
|
30
|
+
Traxis.register_responses
|
31
|
+
|
17
32
|
Dir["#{File.dirname(__FILE__)}/support/*.rb"].each do |file|
|
18
33
|
require file
|
19
34
|
end
|
data/spec/test.db
CHANGED
Binary file
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Traxis::Controller do
|
4
|
+
let(:request) { fake_request }
|
5
|
+
|
6
|
+
subject do
|
7
|
+
::PeopleController.new(fake_request)
|
8
|
+
end
|
9
|
+
|
10
|
+
its(:association_chain) { should eq(::Person) }
|
11
|
+
its(:begin_of_association_chain) { should eq(::Person)}
|
12
|
+
its(:collection) { should be_kind_of(::ActiveRecord::Relation) }
|
13
|
+
its(:collection_relation_name) { should eq "people" }
|
14
|
+
its(:collection_serializer_class) { should eq(::MediaTypes::People) }
|
15
|
+
its(:end_of_association_chain) { should eq :all }
|
16
|
+
its(:method_for_find) { should eq :find }
|
17
|
+
end
|
data/traxis.gemspec
CHANGED
@@ -32,6 +32,8 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency 'guard', '~> 2'
|
33
33
|
spec.add_development_dependency 'guard-rspec', '~> 4'
|
34
34
|
spec.add_development_dependency 'guard-bundler', '~> 2'
|
35
|
+
spec.add_development_dependency 'rb-fsevent'
|
35
36
|
spec.add_development_dependency 'rack-test', '~> 0'
|
36
37
|
spec.add_development_dependency 'simplecov', '~> 0'
|
38
|
+
spec.add_development_dependency 'terminal-notifier-guard'
|
37
39
|
end
|
metadata
CHANGED
@@ -1,236 +1,264 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: traxis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Ayre
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2014-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
15
20
|
requirement: !ruby/object:Gem::Requirement
|
16
21
|
requirements:
|
17
|
-
- -
|
22
|
+
- - '>='
|
18
23
|
- !ruby/object:Gem::Version
|
19
24
|
version: '0'
|
20
|
-
type: :runtime
|
21
25
|
prerelease: false
|
26
|
+
type: :runtime
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
22
29
|
version_requirements: !ruby/object:Gem::Requirement
|
23
30
|
requirements:
|
24
|
-
- -
|
31
|
+
- - '>='
|
25
32
|
- !ruby/object:Gem::Version
|
26
33
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: activerecord
|
29
34
|
requirement: !ruby/object:Gem::Requirement
|
30
35
|
requirements:
|
31
|
-
- -
|
36
|
+
- - '>='
|
32
37
|
- !ruby/object:Gem::Version
|
33
38
|
version: '0'
|
34
|
-
type: :development
|
35
39
|
prerelease: false
|
40
|
+
type: :development
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
36
43
|
version_requirements: !ruby/object:Gem::Requirement
|
37
44
|
requirements:
|
38
|
-
- -
|
45
|
+
- - '>='
|
39
46
|
- !ruby/object:Gem::Version
|
40
47
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: sqlite3
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
44
49
|
requirements:
|
45
|
-
- -
|
50
|
+
- - '>='
|
46
51
|
- !ruby/object:Gem::Version
|
47
52
|
version: '0'
|
48
|
-
type: :development
|
49
53
|
prerelease: false
|
54
|
+
type: :development
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
50
57
|
version_requirements: !ruby/object:Gem::Requirement
|
51
58
|
requirements:
|
52
|
-
- -
|
59
|
+
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: bundler
|
61
|
+
version: '1.6'
|
57
62
|
requirement: !ruby/object:Gem::Requirement
|
58
63
|
requirements:
|
59
|
-
- -
|
64
|
+
- - ~>
|
60
65
|
- !ruby/object:Gem::Version
|
61
66
|
version: '1.6'
|
62
|
-
type: :development
|
63
67
|
prerelease: false
|
68
|
+
type: :development
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
64
71
|
version_requirements: !ruby/object:Gem::Requirement
|
65
72
|
requirements:
|
66
|
-
- -
|
73
|
+
- - '>='
|
67
74
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rake
|
75
|
+
version: '0'
|
71
76
|
requirement: !ruby/object:Gem::Requirement
|
72
77
|
requirements:
|
73
|
-
- -
|
78
|
+
- - '>='
|
74
79
|
- !ruby/object:Gem::Version
|
75
80
|
version: '0'
|
76
|
-
type: :development
|
77
81
|
prerelease: false
|
82
|
+
type: :development
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: praxis
|
78
85
|
version_requirements: !ruby/object:Gem::Requirement
|
79
86
|
requirements:
|
80
|
-
- -
|
87
|
+
- - '>='
|
81
88
|
- !ruby/object:Gem::Version
|
82
89
|
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: praxis
|
85
90
|
requirement: !ruby/object:Gem::Requirement
|
86
91
|
requirements:
|
87
|
-
- -
|
92
|
+
- - '>='
|
88
93
|
- !ruby/object:Gem::Version
|
89
94
|
version: '0'
|
90
|
-
type: :development
|
91
95
|
prerelease: false
|
96
|
+
type: :development
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
92
99
|
version_requirements: !ruby/object:Gem::Requirement
|
93
100
|
requirements:
|
94
|
-
- -
|
101
|
+
- - ~>
|
95
102
|
- !ruby/object:Gem::Version
|
96
103
|
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pry
|
99
104
|
requirement: !ruby/object:Gem::Requirement
|
100
105
|
requirements:
|
101
|
-
- -
|
106
|
+
- - ~>
|
102
107
|
- !ruby/object:Gem::Version
|
103
108
|
version: '0'
|
104
|
-
type: :development
|
105
109
|
prerelease: false
|
110
|
+
type: :development
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
106
113
|
version_requirements: !ruby/object:Gem::Requirement
|
107
114
|
requirements:
|
108
|
-
- -
|
115
|
+
- - ~>
|
109
116
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: rspec
|
117
|
+
version: '3'
|
113
118
|
requirement: !ruby/object:Gem::Requirement
|
114
119
|
requirements:
|
115
|
-
- -
|
120
|
+
- - ~>
|
116
121
|
- !ruby/object:Gem::Version
|
117
122
|
version: '3'
|
118
|
-
type: :development
|
119
123
|
prerelease: false
|
124
|
+
type: :development
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec-its
|
120
127
|
version_requirements: !ruby/object:Gem::Requirement
|
121
128
|
requirements:
|
122
|
-
- -
|
129
|
+
- - ~>
|
123
130
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: rspec-its
|
131
|
+
version: '1'
|
127
132
|
requirement: !ruby/object:Gem::Requirement
|
128
133
|
requirements:
|
129
|
-
- -
|
134
|
+
- - ~>
|
130
135
|
- !ruby/object:Gem::Version
|
131
136
|
version: '1'
|
132
|
-
type: :development
|
133
137
|
prerelease: false
|
138
|
+
type: :development
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec-collection_matchers
|
134
141
|
version_requirements: !ruby/object:Gem::Requirement
|
135
142
|
requirements:
|
136
|
-
- -
|
143
|
+
- - ~>
|
137
144
|
- !ruby/object:Gem::Version
|
138
145
|
version: '1'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: rspec-collection_matchers
|
141
146
|
requirement: !ruby/object:Gem::Requirement
|
142
147
|
requirements:
|
143
|
-
- -
|
148
|
+
- - ~>
|
144
149
|
- !ruby/object:Gem::Version
|
145
150
|
version: '1'
|
146
|
-
type: :development
|
147
151
|
prerelease: false
|
152
|
+
type: :development
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: guard
|
148
155
|
version_requirements: !ruby/object:Gem::Requirement
|
149
156
|
requirements:
|
150
|
-
- -
|
157
|
+
- - ~>
|
151
158
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: guard
|
159
|
+
version: '2'
|
155
160
|
requirement: !ruby/object:Gem::Requirement
|
156
161
|
requirements:
|
157
|
-
- -
|
162
|
+
- - ~>
|
158
163
|
- !ruby/object:Gem::Version
|
159
164
|
version: '2'
|
160
|
-
type: :development
|
161
165
|
prerelease: false
|
166
|
+
type: :development
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: guard-rspec
|
162
169
|
version_requirements: !ruby/object:Gem::Requirement
|
163
170
|
requirements:
|
164
|
-
- -
|
171
|
+
- - ~>
|
165
172
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: guard-rspec
|
173
|
+
version: '4'
|
169
174
|
requirement: !ruby/object:Gem::Requirement
|
170
175
|
requirements:
|
171
|
-
- -
|
176
|
+
- - ~>
|
172
177
|
- !ruby/object:Gem::Version
|
173
178
|
version: '4'
|
174
|
-
type: :development
|
175
179
|
prerelease: false
|
180
|
+
type: :development
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: guard-bundler
|
176
183
|
version_requirements: !ruby/object:Gem::Requirement
|
177
184
|
requirements:
|
178
|
-
- -
|
185
|
+
- - ~>
|
179
186
|
- !ruby/object:Gem::Version
|
180
|
-
version: '
|
181
|
-
- !ruby/object:Gem::Dependency
|
182
|
-
name: guard-bundler
|
187
|
+
version: '2'
|
183
188
|
requirement: !ruby/object:Gem::Requirement
|
184
189
|
requirements:
|
185
|
-
- -
|
190
|
+
- - ~>
|
186
191
|
- !ruby/object:Gem::Version
|
187
192
|
version: '2'
|
188
|
-
type: :development
|
189
193
|
prerelease: false
|
194
|
+
type: :development
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: rb-fsevent
|
190
197
|
version_requirements: !ruby/object:Gem::Requirement
|
191
198
|
requirements:
|
192
|
-
- -
|
199
|
+
- - '>='
|
193
200
|
- !ruby/object:Gem::Version
|
194
|
-
version: '
|
195
|
-
- !ruby/object:Gem::Dependency
|
196
|
-
name: rack-test
|
201
|
+
version: '0'
|
197
202
|
requirement: !ruby/object:Gem::Requirement
|
198
203
|
requirements:
|
199
|
-
- -
|
204
|
+
- - '>='
|
200
205
|
- !ruby/object:Gem::Version
|
201
206
|
version: '0'
|
202
|
-
type: :development
|
203
207
|
prerelease: false
|
208
|
+
type: :development
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: rack-test
|
204
211
|
version_requirements: !ruby/object:Gem::Requirement
|
205
212
|
requirements:
|
206
|
-
- -
|
213
|
+
- - ~>
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
requirement: !ruby/object:Gem::Requirement
|
217
|
+
requirements:
|
218
|
+
- - ~>
|
207
219
|
- !ruby/object:Gem::Version
|
208
220
|
version: '0'
|
221
|
+
prerelease: false
|
222
|
+
type: :development
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
224
|
name: simplecov
|
225
|
+
version_requirements: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ~>
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
211
230
|
requirement: !ruby/object:Gem::Requirement
|
212
231
|
requirements:
|
213
|
-
- -
|
232
|
+
- - ~>
|
214
233
|
- !ruby/object:Gem::Version
|
215
234
|
version: '0'
|
216
|
-
type: :development
|
217
235
|
prerelease: false
|
236
|
+
type: :development
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: terminal-notifier-guard
|
218
239
|
version_requirements: !ruby/object:Gem::Requirement
|
219
240
|
requirements:
|
220
|
-
- -
|
241
|
+
- - '>='
|
221
242
|
- !ruby/object:Gem::Version
|
222
243
|
version: '0'
|
223
|
-
|
224
|
-
|
244
|
+
requirement: !ruby/object:Gem::Requirement
|
245
|
+
requirements:
|
246
|
+
- - '>='
|
247
|
+
- !ruby/object:Gem::Version
|
248
|
+
version: '0'
|
249
|
+
prerelease: false
|
250
|
+
type: :development
|
251
|
+
description: Making Praxis more like rails with active record, inherited resources inspired conventions
|
225
252
|
email:
|
226
253
|
- jasonayre@gmail.com
|
227
254
|
executables: []
|
228
255
|
extensions: []
|
229
256
|
extra_rdoc_files: []
|
230
257
|
files:
|
231
|
-
-
|
232
|
-
-
|
258
|
+
- .gitignore
|
259
|
+
- .rspec
|
233
260
|
- Gemfile
|
261
|
+
- Guardfile
|
234
262
|
- LICENSE.txt
|
235
263
|
- README.md
|
236
264
|
- Rakefile
|
@@ -241,6 +269,18 @@ files:
|
|
241
269
|
- lib/traxis/response.rb
|
242
270
|
- lib/traxis/responses.rb
|
243
271
|
- lib/traxis/version.rb
|
272
|
+
- spec/helpers/base.rb
|
273
|
+
- spec/spec_app/app/controllers/instances.rb
|
274
|
+
- spec/spec_app/app/responses/bulk_response.rb
|
275
|
+
- spec/spec_app/app/responses/multipart.rb
|
276
|
+
- spec/spec_app/app/responses/other_response.rb
|
277
|
+
- spec/spec_app/config.ru
|
278
|
+
- spec/spec_app/config/environment.rb
|
279
|
+
- spec/spec_app/design/api.rb
|
280
|
+
- spec/spec_app/design/media_types/instance.rb
|
281
|
+
- spec/spec_app/design/media_types/volume.rb
|
282
|
+
- spec/spec_app/design/media_types/volume_snapshot.rb
|
283
|
+
- spec/spec_app/design/resources/instances.rb
|
244
284
|
- spec/spec_helper.rb
|
245
285
|
- spec/support/db.rb
|
246
286
|
- spec/support/media_types.rb
|
@@ -248,33 +288,46 @@ files:
|
|
248
288
|
- spec/support/resource_definitions.rb
|
249
289
|
- spec/test.db
|
250
290
|
- spec/traxis/controller_actions_spec.rb
|
291
|
+
- spec/traxis/controller_helpers_spec.rb
|
251
292
|
- spec/traxis/response_definition_spec.rb
|
252
293
|
- traxis.gemspec
|
253
294
|
homepage: http://github.com/jasonayre/traxis
|
254
295
|
licenses:
|
255
296
|
- MIT
|
256
297
|
metadata: {}
|
257
|
-
post_install_message:
|
298
|
+
post_install_message:
|
258
299
|
rdoc_options: []
|
259
300
|
require_paths:
|
260
301
|
- lib
|
261
302
|
required_ruby_version: !ruby/object:Gem::Requirement
|
262
303
|
requirements:
|
263
|
-
- -
|
304
|
+
- - '>='
|
264
305
|
- !ruby/object:Gem::Version
|
265
306
|
version: '0'
|
266
307
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
308
|
requirements:
|
268
|
-
- -
|
309
|
+
- - '>='
|
269
310
|
- !ruby/object:Gem::Version
|
270
311
|
version: '0'
|
271
312
|
requirements: []
|
272
|
-
rubyforge_project:
|
313
|
+
rubyforge_project:
|
273
314
|
rubygems_version: 2.2.2
|
274
|
-
signing_key:
|
315
|
+
signing_key:
|
275
316
|
specification_version: 4
|
276
317
|
summary: Strongly opinionated restful api convention > config for praxis
|
277
318
|
test_files:
|
319
|
+
- spec/helpers/base.rb
|
320
|
+
- spec/spec_app/app/controllers/instances.rb
|
321
|
+
- spec/spec_app/app/responses/bulk_response.rb
|
322
|
+
- spec/spec_app/app/responses/multipart.rb
|
323
|
+
- spec/spec_app/app/responses/other_response.rb
|
324
|
+
- spec/spec_app/config.ru
|
325
|
+
- spec/spec_app/config/environment.rb
|
326
|
+
- spec/spec_app/design/api.rb
|
327
|
+
- spec/spec_app/design/media_types/instance.rb
|
328
|
+
- spec/spec_app/design/media_types/volume.rb
|
329
|
+
- spec/spec_app/design/media_types/volume_snapshot.rb
|
330
|
+
- spec/spec_app/design/resources/instances.rb
|
278
331
|
- spec/spec_helper.rb
|
279
332
|
- spec/support/db.rb
|
280
333
|
- spec/support/media_types.rb
|
@@ -282,4 +335,5 @@ test_files:
|
|
282
335
|
- spec/support/resource_definitions.rb
|
283
336
|
- spec/test.db
|
284
337
|
- spec/traxis/controller_actions_spec.rb
|
338
|
+
- spec/traxis/controller_helpers_spec.rb
|
285
339
|
- spec/traxis/response_definition_spec.rb
|