toast 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controller/toast_controller.rb +1 -1
- data/config/routes.rb +19 -11
- data/lib/toast/active_record_extensions.rb +34 -27
- data/lib/toast/association.rb +29 -19
- data/lib/toast/collection.rb +23 -16
- data/lib/toast/config_dsl.rb +17 -4
- data/lib/toast/engine.rb +1 -0
- data/lib/toast/record.rb +22 -14
- data/lib/toast/resource.rb +49 -17
- data/lib/toast/single.rb +11 -7
- metadata +17 -4
@@ -6,7 +6,7 @@ class ToastController < ApplicationController
|
|
6
6
|
|
7
7
|
@resource = Toast::Resource.build( params, request )
|
8
8
|
|
9
|
-
render @resource.apply(request.method, request.body.read)
|
9
|
+
render @resource.apply(request.method, request.body.read, request.content_type)
|
10
10
|
|
11
11
|
rescue Toast::ResourceNotFound => e
|
12
12
|
return head(:not_found)
|
data/config/routes.rb
CHANGED
@@ -5,17 +5,25 @@ Rails.application.routes.draw do
|
|
5
5
|
|
6
6
|
resource_name = model.to_s.pluralize.underscore
|
7
7
|
|
8
|
-
|
9
|
-
:constraints => { :id => /\d+/ },
|
10
|
-
:resource => resource_name,
|
11
|
-
:as => resource_name,
|
12
|
-
:defaults => { :format => 'json' })
|
13
|
-
|
14
|
-
match("#{model.toast_config.namespace}/#{resource_name}/:subresource" => 'toast#catch_all',
|
15
|
-
:resource => resource_name,
|
16
|
-
:defaults => { :format => 'json' })
|
17
|
-
end
|
8
|
+
namespaces = []
|
18
9
|
|
19
|
-
|
10
|
+
# routes must be defined for all defined namespaces of a model
|
11
|
+
model.toast_configs.each do |tc|
|
12
|
+
# once per namespace
|
13
|
+
next if namespaces.include? tc.namespace
|
14
|
+
|
15
|
+
namespaces << tc.namespace
|
16
|
+
|
17
|
+
match("#{tc.namespace}/#{resource_name}(/:id(/:subresource))" => 'toast#catch_all',
|
18
|
+
:constraints => { :id => /\d+/ },
|
19
|
+
:resource => resource_name,
|
20
|
+
:as => resource_name,
|
21
|
+
:defaults => { :format => 'json' })
|
20
22
|
|
23
|
+
match("#{tc.namespace}/#{resource_name}/:subresource" => 'toast#catch_all',
|
24
|
+
:resource => resource_name,
|
25
|
+
:defaults => { :format => 'json' })
|
26
|
+
end
|
27
|
+
end
|
21
28
|
|
29
|
+
end
|
@@ -4,57 +4,64 @@ require 'toast/config_dsl'
|
|
4
4
|
module Toast
|
5
5
|
module ActiveRecordExtensions
|
6
6
|
|
7
|
-
# Configuration DSL
|
8
|
-
def
|
9
|
-
|
10
|
-
|
7
|
+
# Configuration DSL
|
8
|
+
def acts_as_resource &block
|
9
|
+
|
10
|
+
@toast_configs ||= Array.new
|
11
|
+
|
12
|
+
@toast_configs << Toast::ConfigDSL::Base.new(self)
|
13
|
+
|
14
|
+
Blockenspiel.invoke( block, @toast_configs.last)
|
11
15
|
|
12
16
|
# add class methods
|
13
17
|
self.instance_eval do
|
14
18
|
|
15
|
-
cattr_accessor :uri_base
|
16
|
-
|
17
19
|
def is_resourceful_model?
|
18
20
|
true
|
19
21
|
end
|
20
22
|
|
21
|
-
def
|
22
|
-
@
|
23
|
+
def toast_configs
|
24
|
+
@toast_configs
|
25
|
+
end
|
26
|
+
|
27
|
+
# get a config by media type or first one if none matches
|
28
|
+
def toast_config media_type
|
29
|
+
@toast_configs.find do |tc|
|
30
|
+
tc.media_type == media_type || tc.in_collection.media_type == media_type
|
31
|
+
end || @toast_configs.first
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
26
35
|
# add instance methods
|
27
36
|
self.class_eval do
|
28
37
|
# Return the path segment of the URI of this record
|
29
|
-
def
|
38
|
+
def uri_path
|
30
39
|
"/" +
|
31
|
-
(self.class.toast_config.namespace ? self.class.toast_config.namespace+"/" : "") +
|
32
40
|
self.class.to_s.pluralize.underscore + "/" +
|
33
41
|
self.id.to_s
|
34
42
|
end
|
43
|
+
|
44
|
+
# Like ActiveRecord::Base.attributes, but result Hash includes
|
45
|
+
# only attributes from the list _attr_names_ plus the
|
46
|
+
# associations _assoc_names_ as links and the 'self' link
|
47
|
+
def represent attr_names, assoc_names, base_uri
|
48
|
+
props = {}
|
35
49
|
|
36
|
-
|
37
|
-
|
38
|
-
options.reverse_merge! :in_collection => false,
|
39
|
-
:with_uri => true
|
40
|
-
|
41
|
-
# attributes
|
42
|
-
exposed_attr =
|
43
|
-
options[:in_collection] ? self.class.toast_config.in_collection.exposed_attributes :
|
44
|
-
self.class.toast_config.exposed_attributes
|
45
|
-
|
46
|
-
out = exposed_attr.inject({}) do |acc, attr|
|
47
|
-
acc[attr] = self.send attr
|
48
|
-
acc
|
50
|
+
attr_names.each do |name|
|
51
|
+
props[name] = self.send(name)
|
49
52
|
end
|
50
|
-
|
51
|
-
|
53
|
+
|
54
|
+
assoc_names.each do |name|
|
55
|
+
props[name] = "#{base_uri}#{self.uri_path}/#{name}"
|
56
|
+
end
|
57
|
+
|
58
|
+
props["self"] = base_uri + self.uri_path
|
59
|
+
|
60
|
+
props
|
52
61
|
end
|
53
62
|
end
|
54
63
|
end
|
55
64
|
|
56
|
-
alias acts_as_resource resourceful_model
|
57
|
-
|
58
65
|
# defaults for non resourceful-models
|
59
66
|
def is_resourceful_model?
|
60
67
|
false
|
data/lib/toast/association.rb
CHANGED
@@ -3,8 +3,9 @@ module Toast
|
|
3
3
|
|
4
4
|
attr_reader :model
|
5
5
|
|
6
|
-
def initialize model, id, subresource_name, format
|
7
|
-
|
6
|
+
def initialize model, id, subresource_name, format, config, assoc_model, assoc_config_in, assoc_config_out
|
7
|
+
|
8
|
+
unless config.exposed_associations.include? subresource_name
|
8
9
|
raise ResourceNotFound
|
9
10
|
end
|
10
11
|
|
@@ -13,28 +14,35 @@ module Toast
|
|
13
14
|
@assoc = subresource_name
|
14
15
|
@format = format
|
15
16
|
@is_collection = [:has_many, :has_and_belongs_to_many].include? @model.reflect_on_association(@assoc.to_sym).macro
|
16
|
-
|
17
|
-
@associate_model =
|
18
|
-
@
|
17
|
+
@config = config
|
18
|
+
@associate_model = assoc_model
|
19
|
+
@associate_config_in = assoc_config_in
|
20
|
+
@associate_config_out = assoc_config_out
|
19
21
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def get
|
23
25
|
result = @record.send(@assoc)
|
24
26
|
|
27
|
+
raise ResourceNotFound if result.nil?
|
28
|
+
|
25
29
|
if result.is_a? Array
|
26
30
|
{
|
27
31
|
:json => result.map{|r|
|
28
|
-
r.
|
29
|
-
|
32
|
+
r.represent( @associate_config_out.in_collection.exposed_attributes,
|
33
|
+
@associate_config_out.in_collection.exposed_associations,
|
34
|
+
@base_uri )
|
30
35
|
},
|
31
|
-
:status => :ok
|
36
|
+
:status => :ok,
|
37
|
+
:content_type => @associate_config_out.in_collection.media_type
|
32
38
|
}
|
33
39
|
else
|
34
40
|
{
|
35
|
-
:json =>
|
36
|
-
|
37
|
-
|
41
|
+
:json => result.represent( @associate_config_out.exposed_attributes,
|
42
|
+
@associate_config_out.exposed_associations,
|
43
|
+
@base_uri ),
|
44
|
+
:status => :ok,
|
45
|
+
:content_type => @associate_config_out.media_type
|
38
46
|
}
|
39
47
|
end
|
40
48
|
|
@@ -44,10 +52,10 @@ module Toast
|
|
44
52
|
raise MethodNotAllowed
|
45
53
|
end
|
46
54
|
|
47
|
-
def post payload
|
48
|
-
raise MethodNotAllowed unless @
|
55
|
+
def post payload, media_type
|
56
|
+
raise MethodNotAllowed unless @config.writables.include? @assoc
|
49
57
|
|
50
|
-
if
|
58
|
+
if media_type != @associate_config_in.media_type
|
51
59
|
raise UnsupportedMediaType
|
52
60
|
end
|
53
61
|
|
@@ -63,18 +71,20 @@ module Toast
|
|
63
71
|
|
64
72
|
|
65
73
|
# silently ignore all exposed readable, but not writable fields
|
66
|
-
(@
|
74
|
+
(@associate_config_in.readables - @associate_config_in.writables).each do |rof|
|
67
75
|
payload.delete(rof)
|
68
76
|
end
|
69
77
|
|
70
|
-
|
71
78
|
begin
|
72
79
|
record = @record.send(@assoc).create! payload
|
73
80
|
|
74
81
|
{
|
75
|
-
:json => record.
|
76
|
-
|
77
|
-
|
82
|
+
:json => record.represent( @associate_config_out.exposed_attributes,
|
83
|
+
@associate_config_out.exposed_associations,
|
84
|
+
@base_uri ),
|
85
|
+
:location => self.base_uri + record.uri_path,
|
86
|
+
:status => :created,
|
87
|
+
:content_type => @associate_config_out.media_type
|
78
88
|
}
|
79
89
|
|
80
90
|
rescue ActiveRecord::RecordInvalid => e
|
data/lib/toast/collection.rb
CHANGED
@@ -3,11 +3,11 @@ module Toast
|
|
3
3
|
|
4
4
|
attr_reader :model
|
5
5
|
|
6
|
-
def initialize model, subresource_name, params
|
6
|
+
def initialize model, subresource_name, params, config_in, config_out
|
7
7
|
|
8
8
|
subresource_name ||= "all"
|
9
9
|
|
10
|
-
unless
|
10
|
+
unless config_out.collections.include? subresource_name
|
11
11
|
raise ResourceNotFound
|
12
12
|
end
|
13
13
|
|
@@ -15,11 +15,13 @@ module Toast
|
|
15
15
|
@collection = subresource_name
|
16
16
|
@params = params
|
17
17
|
@format = params[:format]
|
18
|
+
@config_out = config_out
|
19
|
+
@config_in = config_in
|
18
20
|
end
|
19
21
|
|
20
22
|
def get
|
21
23
|
|
22
|
-
records = if @
|
24
|
+
records = if @config_out.pass_params_to.include?(@collection)
|
23
25
|
@model.send(@collection, @params)
|
24
26
|
else
|
25
27
|
@model.send(@collection)
|
@@ -34,10 +36,12 @@ module Toast
|
|
34
36
|
when "json"
|
35
37
|
{
|
36
38
|
:json => records.map{|r|
|
37
|
-
r.
|
38
|
-
|
39
|
+
r.represent( @config_out.in_collection.exposed_attributes,
|
40
|
+
@config_out.in_collection.exposed_associations,
|
41
|
+
@base_uri )
|
39
42
|
},
|
40
|
-
:status => :ok
|
43
|
+
:status => :ok,
|
44
|
+
:content_type => @config_out.in_collection.media_type
|
41
45
|
}
|
42
46
|
else
|
43
47
|
raise ResourceNotFound
|
@@ -48,15 +52,15 @@ module Toast
|
|
48
52
|
raise MethodNotAllowed
|
49
53
|
end
|
50
54
|
|
51
|
-
def post payload
|
52
|
-
raise MethodNotAllowed unless @
|
55
|
+
def post payload, media_type
|
56
|
+
raise MethodNotAllowed unless @config_in.postable?
|
53
57
|
|
54
|
-
if
|
55
|
-
raise
|
58
|
+
if media_type != @config_in.media_type
|
59
|
+
raise UnsupportedMediaType
|
56
60
|
end
|
57
61
|
|
58
|
-
if
|
59
|
-
raise
|
62
|
+
if @collection != "all"
|
63
|
+
raise MethodNotAllowed
|
60
64
|
end
|
61
65
|
|
62
66
|
begin
|
@@ -69,7 +73,7 @@ module Toast
|
|
69
73
|
end
|
70
74
|
|
71
75
|
# silently ignore all exposed readable, but not writable fields
|
72
|
-
(@
|
76
|
+
(@config_in.readables - @config_in.writables + ["self"]).each do |rof|
|
73
77
|
payload.delete(rof)
|
74
78
|
end
|
75
79
|
|
@@ -77,9 +81,12 @@ module Toast
|
|
77
81
|
record = @model.create! payload
|
78
82
|
|
79
83
|
{
|
80
|
-
:json => record.
|
81
|
-
|
82
|
-
|
84
|
+
:json => record.represent( @config_out.exposed_attributes,
|
85
|
+
@config_out.exposed_associations,
|
86
|
+
@base_uri ),
|
87
|
+
:location => @base_uri + record.uri_path,
|
88
|
+
:status => :created,
|
89
|
+
:content_type => @config_out.media_type
|
83
90
|
}
|
84
91
|
|
85
92
|
rescue ActiveRecord::RecordInvalid => e
|
data/lib/toast/config_dsl.rb
CHANGED
@@ -3,7 +3,7 @@ module Toast
|
|
3
3
|
|
4
4
|
class Base
|
5
5
|
include Blockenspiel::DSL
|
6
|
-
dsl_attr_accessor :
|
6
|
+
dsl_attr_accessor :namespace, :media_type
|
7
7
|
|
8
8
|
def initialize model
|
9
9
|
@model = model
|
@@ -11,11 +11,11 @@ module Toast
|
|
11
11
|
@writables = []
|
12
12
|
@collections = []
|
13
13
|
@singles = []
|
14
|
-
@media_type = "application/json"
|
15
14
|
@deletable = false
|
16
15
|
@postable = false
|
17
16
|
@pass_params_to = []
|
18
17
|
@in_collection = ConfigDSL::InCollection.new model, self
|
18
|
+
@media_type = "application/json"
|
19
19
|
end
|
20
20
|
|
21
21
|
def exposed_attributes
|
@@ -107,11 +107,13 @@ module Toast
|
|
107
107
|
class InCollection
|
108
108
|
include Blockenspiel::DSL
|
109
109
|
|
110
|
+
dsl_attr_accessor :media_type
|
111
|
+
|
110
112
|
def initialize model, base_config
|
111
113
|
@model = model
|
114
|
+
@media_type = "application/json"
|
112
115
|
@readables = base_config.readables # must assign a reference
|
113
116
|
@writables = base_config.writables # must assign a reference
|
114
|
-
@media_type = "application/json"
|
115
117
|
end
|
116
118
|
|
117
119
|
def readables= readables
|
@@ -127,13 +129,23 @@ module Toast
|
|
127
129
|
def writables *arg
|
128
130
|
self.writables = 42
|
129
131
|
end
|
130
|
-
|
132
|
+
|
131
133
|
def writables= arg
|
132
134
|
puts
|
133
135
|
puts "Toast Config Warning (#{model.class}): Defining \"writables\" in collection definition has no effect."
|
134
136
|
puts
|
135
137
|
end
|
136
138
|
|
139
|
+
def namespace *arg
|
140
|
+
self.writables = 42
|
141
|
+
end
|
142
|
+
|
143
|
+
def namespace= arg
|
144
|
+
puts
|
145
|
+
puts "Toast Config Warning (#{model.class}): Defining \"namespace\" in collection definition has no effect."
|
146
|
+
puts
|
147
|
+
end
|
148
|
+
|
137
149
|
def exposed_attributes
|
138
150
|
assocs = @model.reflect_on_all_associations.map{|a| a.name.to_s}
|
139
151
|
(@readables + @writables).uniq.select{|f| !assocs.include?(f)}
|
@@ -143,6 +155,7 @@ module Toast
|
|
143
155
|
assocs = @model.reflect_on_all_associations.map{|a| a.name.to_s}
|
144
156
|
(@readables + @writables).uniq.select{|f| assocs.include?(f)}
|
145
157
|
end
|
158
|
+
|
146
159
|
end
|
147
160
|
|
148
161
|
|
data/lib/toast/engine.rb
CHANGED
data/lib/toast/record.rb
CHANGED
@@ -3,22 +3,24 @@ module Toast
|
|
3
3
|
|
4
4
|
attr_reader :model
|
5
5
|
|
6
|
-
def initialize model, id, format
|
6
|
+
def initialize model, id, format, config_in, config_out
|
7
7
|
@model = model
|
8
8
|
@record = model.find(id) rescue raise(ResourceNotFound.new)
|
9
9
|
@format = format
|
10
|
+
@config_in = config_in
|
11
|
+
@config_out = config_out
|
10
12
|
end
|
11
13
|
|
12
|
-
def post payload
|
14
|
+
def post payload, media_type
|
13
15
|
raise MethodNotAllowed
|
14
16
|
end
|
15
17
|
|
16
18
|
# get, put, delete, post return a Hash that can be used as
|
17
19
|
# argument for ActionController#render
|
18
20
|
|
19
|
-
def put payload
|
21
|
+
def put payload, media_type
|
20
22
|
|
21
|
-
if
|
23
|
+
if media_type != @config_in.media_type
|
22
24
|
raise UnsupportedMediaType
|
23
25
|
end
|
24
26
|
|
@@ -33,21 +35,24 @@ module Toast
|
|
33
35
|
end
|
34
36
|
|
35
37
|
# ignore all exposed readable, but not writable fields
|
36
|
-
(@
|
38
|
+
(@config_in.readables - @config_in.writables + ["self"]).each do |rof|
|
37
39
|
payload.delete(rof)
|
38
40
|
end
|
39
|
-
|
41
|
+
|
40
42
|
# set the virtual attributes
|
41
|
-
(
|
43
|
+
(@config_in.writables - @record.attribute_names - @config_in.exposed_associations).each do |vattr|
|
42
44
|
@record.send("#{vattr}=", payload.delete(vattr))
|
43
45
|
end
|
44
|
-
|
46
|
+
|
45
47
|
# mass-update for the rest
|
46
48
|
@record.update_attributes payload
|
47
|
-
{
|
48
|
-
:json => @record.
|
49
|
+
{
|
50
|
+
:json => @record.represent( @config_out.exposed_attributes,
|
51
|
+
@config_out.exposed_associations,
|
52
|
+
@base_uri ),
|
49
53
|
:status => :ok,
|
50
|
-
:location => self.base_uri + @record.
|
54
|
+
:location => self.base_uri + @record.uri_path,
|
55
|
+
:content_type => @config_out.media_type
|
51
56
|
}
|
52
57
|
end
|
53
58
|
|
@@ -60,8 +65,11 @@ module Toast
|
|
60
65
|
}
|
61
66
|
when "json"
|
62
67
|
{
|
63
|
-
:json => @record.
|
64
|
-
|
68
|
+
:json => @record.represent( @config_out.exposed_attributes,
|
69
|
+
@config_out.exposed_associations,
|
70
|
+
@base_uri ),
|
71
|
+
:status => :ok,
|
72
|
+
:content_type => @config_out.media_type
|
65
73
|
}
|
66
74
|
else
|
67
75
|
raise ResourceNotFound
|
@@ -69,7 +77,7 @@ module Toast
|
|
69
77
|
end
|
70
78
|
|
71
79
|
def delete
|
72
|
-
raise MethodNotAllowed unless @
|
80
|
+
raise MethodNotAllowed unless @config_out.deletable?
|
73
81
|
|
74
82
|
@record.destroy
|
75
83
|
{
|
data/lib/toast/resource.rb
CHANGED
@@ -5,12 +5,13 @@ module Toast
|
|
5
5
|
class PayloadInvalid < Exception; end
|
6
6
|
class PayloadFormatError < Exception; end
|
7
7
|
class UnsupportedMediaType < Exception; end
|
8
|
+
class RequestedVersionNotDefined < Exception; end
|
8
9
|
|
9
10
|
# Represents a resource. There are following resource types as sub classes:
|
10
11
|
# Record, Collection, Association, Single
|
11
12
|
class Resource
|
12
13
|
|
13
|
-
attr_accessor :
|
14
|
+
attr_accessor :prefered_media_type, :base_uri, :payload_content_type
|
14
15
|
|
15
16
|
def initialize
|
16
17
|
raise 'ToastResource#new: use #build to create an instance'
|
@@ -22,25 +23,56 @@ module Toast
|
|
22
23
|
subresource_name = params[:subresource]
|
23
24
|
format = params[:format]
|
24
25
|
|
25
|
-
|
26
|
+
#### Debugging stop
|
27
|
+
# binding.pry if $halt
|
28
|
+
###
|
26
29
|
|
30
|
+
begin
|
31
|
+
|
32
|
+
# determine model
|
27
33
|
model = get_class_by_resource_name resource_name
|
28
|
-
|
29
|
-
#
|
30
|
-
|
31
|
-
|
34
|
+
|
35
|
+
# determine config for representation
|
36
|
+
# config_in: cosumed representation
|
37
|
+
# config_out: produced representation
|
38
|
+
config_out = model.toast_config request.accept_media_types.prefered
|
39
|
+
config_in = model.toast_config request.media_type
|
40
|
+
|
41
|
+
# ... or in case of an association request
|
42
|
+
config_assoc_src = model.toast_config request.headers["Assoc-source-type"]
|
43
|
+
|
44
|
+
# base URI for returned object
|
45
|
+
base_uri = request.base_url + request.script_name +
|
46
|
+
(config_out.namespace ? "/" + config_out.namespace : "")
|
47
|
+
|
48
|
+
# decide which sub resource type
|
49
|
+
rsc = if id.nil? and config_out.singles.include?(subresource_name)
|
50
|
+
Toast::Single.new(model, subresource_name, params.clone, config_in, config_out)
|
32
51
|
elsif id.nil?
|
33
|
-
Toast::Collection.new(model, subresource_name, params.clone)
|
52
|
+
Toast::Collection.new(model, subresource_name, params.clone, config_in, config_out)
|
34
53
|
elsif subresource_name.nil?
|
35
|
-
Toast::Record.new(model, id, format)
|
36
|
-
elsif
|
37
|
-
|
54
|
+
Toast::Record.new(model, id, format, config_in, config_out)
|
55
|
+
elsif (config_assoc_src && config_assoc_src.exposed_associations.include?(subresource_name))
|
56
|
+
|
57
|
+
# determine associated model
|
58
|
+
assoc_model = get_class_by_resource_name subresource_name
|
59
|
+
|
60
|
+
# determine config for representation of assoc. model
|
61
|
+
assoc_config_out = assoc_model.toast_config request.accept_media_types.prefered
|
62
|
+
assoc_config_in = assoc_model.toast_config request.media_type
|
63
|
+
|
64
|
+
# change base URI to associated record
|
65
|
+
base_uri = request.base_url + request.script_name +
|
66
|
+
(assoc_config_out.namespace ? "/" + assoc_config_out.namespace : "")
|
67
|
+
|
68
|
+
Toast::Association.new(model, id, subresource_name, format, config_assoc_src,
|
69
|
+
assoc_model, assoc_config_in, assoc_config_out)
|
38
70
|
else
|
39
71
|
raise ResourceNotFound
|
40
72
|
end
|
41
73
|
|
42
|
-
|
43
|
-
rsc.base_uri =
|
74
|
+
# set base to be prepended to URIs
|
75
|
+
rsc.base_uri = base_uri
|
44
76
|
|
45
77
|
rsc
|
46
78
|
rescue NameError
|
@@ -63,10 +95,10 @@ module Toast
|
|
63
95
|
end
|
64
96
|
end
|
65
97
|
|
66
|
-
def apply method, payload
|
98
|
+
def apply method, payload, payload_media_type
|
67
99
|
case method
|
68
|
-
when "PUT","POST"
|
69
|
-
self.send(method.downcase, payload)
|
100
|
+
when "PUT","POST"
|
101
|
+
self.send(method.downcase, payload, payload_media_type)
|
70
102
|
when "DELETE","GET"
|
71
103
|
self.send(method.downcase)
|
72
104
|
else
|
@@ -83,10 +115,10 @@ module Toast
|
|
83
115
|
record.class.toast_config.exposed_associations
|
84
116
|
|
85
117
|
exposed_assoc.each do |assoc|
|
86
|
-
out[assoc] = "#{self.base_uri}#{record.
|
118
|
+
out[assoc] = "#{self.base_uri}#{record.uri_path}/#{assoc}"
|
87
119
|
end
|
88
120
|
|
89
|
-
out["
|
121
|
+
out["self"] = self.base_uri + record.uri_path
|
90
122
|
|
91
123
|
out
|
92
124
|
end
|
data/lib/toast/single.rb
CHANGED
@@ -13,9 +13,11 @@ module Toast
|
|
13
13
|
|
14
14
|
attr_reader :model
|
15
15
|
|
16
|
-
def initialize model, subresource_name, params
|
16
|
+
def initialize model, subresource_name, params, config_in, config_out
|
17
|
+
@config_in = config_in
|
18
|
+
@config_out = config_out
|
17
19
|
|
18
|
-
unless
|
20
|
+
unless @config_out.singles.include? subresource_name
|
19
21
|
raise ResourceNotFound
|
20
22
|
end
|
21
23
|
|
@@ -23,14 +25,14 @@ module Toast
|
|
23
25
|
@params = params
|
24
26
|
@format = params[:format]
|
25
27
|
|
26
|
-
|
28
|
+
|
29
|
+
@record = if @config_out.pass_params_to.include?(subresource_name)
|
27
30
|
@model.send(subresource_name, @params)
|
28
31
|
else
|
29
32
|
@model.send(subresource_name)
|
30
33
|
end
|
31
|
-
|
32
|
-
raise ResourceNotFound if @record.nil?
|
33
|
-
|
34
|
+
|
35
|
+
raise ResourceNotFound if @record.nil?
|
34
36
|
end
|
35
37
|
|
36
38
|
def get
|
@@ -42,7 +44,9 @@ module Toast
|
|
42
44
|
}
|
43
45
|
when "json"
|
44
46
|
{
|
45
|
-
:json => @record.
|
47
|
+
:json => @record.represent( @config_out.exposed_attributes,
|
48
|
+
@config_out.exposed_associations,
|
49
|
+
@base_uri ),
|
46
50
|
:status => :ok
|
47
51
|
}
|
48
52
|
else
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Robert Annies
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-
|
17
|
+
date: 2012-05-31 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -31,6 +31,19 @@ dependencies:
|
|
31
31
|
version: 0.4.2
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rack-accept-media-types
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 9
|
44
|
+
version: "0.9"
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
34
47
|
description: |-
|
35
48
|
Toast is an extension to Ruby on Rails that lets you expose any
|
36
49
|
ActiveRecord model as a resource according to the REST paradigm. The
|