toast 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/config/routes.rb +3 -3
- data/lib/toast/active_record_extensions.rb +14 -24
- data/lib/toast/collection.rb +14 -26
- data/lib/toast/config_dsl.rb +1 -13
- data/lib/toast/engine.rb +0 -1
- data/lib/toast/record.rb +8 -5
- data/lib/toast/resource.rb +17 -20
- data/lib/toast/version.rb +1 -1
- metadata +5 -6
- data/lib/toast/scoped_association.rb +0 -23
data/config/routes.rb
CHANGED
@@ -11,10 +11,10 @@ Rails.application.routes.draw do
|
|
11
11
|
model.toast_configs.each do |tc|
|
12
12
|
# once per namespace
|
13
13
|
next if namespaces.include? tc.namespace
|
14
|
-
|
14
|
+
|
15
15
|
namespaces << tc.namespace
|
16
|
-
|
17
|
-
match("#{tc.namespace}/#{resource_name}(/:id(/:subresource
|
16
|
+
|
17
|
+
match("#{tc.namespace}/#{resource_name}(/:id(/:subresource))" => 'toast#catch_all',
|
18
18
|
:constraints => { :id => /\d+/ },
|
19
19
|
:resource => resource_name,
|
20
20
|
:as => resource_name,
|
@@ -4,13 +4,13 @@ require 'toast/config_dsl'
|
|
4
4
|
module Toast
|
5
5
|
module ActiveRecordExtensions
|
6
6
|
|
7
|
-
# Configuration DSL
|
7
|
+
# Configuration DSL
|
8
8
|
def acts_as_resource &block
|
9
9
|
|
10
|
-
@toast_configs ||= Array.new
|
11
|
-
|
10
|
+
@toast_configs ||= Array.new
|
11
|
+
|
12
12
|
@toast_configs << Toast::ConfigDSL::Base.new(self)
|
13
|
-
|
13
|
+
|
14
14
|
Blockenspiel.invoke( block, @toast_configs.last)
|
15
15
|
|
16
16
|
# add class methods
|
@@ -23,12 +23,12 @@ module Toast
|
|
23
23
|
def toast_configs
|
24
24
|
@toast_configs
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
# get a config by media type or first one if none matches
|
28
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
|
29
|
+
@toast_configs.find do |tc|
|
30
|
+
tc.media_type == media_type || tc.in_collection.media_type == media_type
|
31
|
+
end || @toast_configs.first
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -40,36 +40,26 @@ module Toast
|
|
40
40
|
self.class.to_s.pluralize.underscore + "/" +
|
41
41
|
self.id.to_s
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# Like ActiveRecord::Base.attributes, but result Hash includes
|
45
45
|
# only attributes from the list _attr_names_ plus the
|
46
46
|
# associations _assoc_names_ as links and the 'self' link
|
47
47
|
def represent attr_names, assoc_names, base_uri, media_type
|
48
48
|
props = {}
|
49
49
|
|
50
|
-
attr_names.each do |name|
|
50
|
+
attr_names.each do |name|
|
51
51
|
unless self.respond_to?(name) && self.method(name).arity == 0
|
52
52
|
raise "Toast Error: Connot find instance method '#{self.class}##{name}' of arity 0"
|
53
53
|
end
|
54
54
|
props[name] = self.send(name)
|
55
55
|
end
|
56
|
-
|
57
|
-
assoc_names.each do |name|
|
56
|
+
|
57
|
+
assoc_names.each do |name|
|
58
58
|
props[name] = "#{base_uri}#{self.uri_path}/#{name}"
|
59
|
-
|
60
|
-
# collections (scopes) actiing on associacions:
|
61
|
-
|
62
|
-
reflect = self.class.reflect_on_association(name.to_sym)
|
63
|
-
if reflect.collection?
|
64
|
-
reflect.klass.toast_config(media_type).collections.each do |collection_name|
|
65
|
-
next if collection_name == "all"
|
66
|
-
props[name+":"+collection_name] = "#{base_uri}#{self.uri_path}/#{name}/#{collection_name}"
|
67
|
-
end
|
68
|
-
end
|
69
59
|
end
|
70
|
-
|
60
|
+
|
71
61
|
props["self"] = base_uri + self.uri_path
|
72
|
-
|
62
|
+
|
73
63
|
props
|
74
64
|
end
|
75
65
|
end
|
data/lib/toast/collection.rb
CHANGED
@@ -3,22 +3,18 @@ module Toast
|
|
3
3
|
|
4
4
|
attr_reader :model
|
5
5
|
|
6
|
-
def initialize
|
6
|
+
def initialize model, subresource_name, params, config_in, config_out
|
7
7
|
|
8
8
|
subresource_name ||= "all"
|
9
9
|
|
10
10
|
unless config_out.collections.include? subresource_name
|
11
11
|
if subresource_name == "all"
|
12
|
-
ToastController.logger.debug "\n\tToast Debug: you may want to declare 'collections :all' in model '#{
|
12
|
+
ToastController.logger.debug "\n\tToast Debug: you may want to declare 'collections :all' in model '#{model}' to enable delivery of the collection '/#{model.to_s.underscore.pluralize}'\n"
|
13
13
|
end
|
14
14
|
raise ResourceNotFound
|
15
15
|
end
|
16
16
|
|
17
|
-
@
|
18
|
-
model_or_relation.klass :
|
19
|
-
model_or_relation
|
20
|
-
|
21
|
-
@model_or_relation = model_or_relation
|
17
|
+
@model = model
|
22
18
|
@collection = subresource_name
|
23
19
|
@params = params
|
24
20
|
@format = params[:format]
|
@@ -28,8 +24,8 @@ module Toast
|
|
28
24
|
|
29
25
|
def get
|
30
26
|
|
31
|
-
unless @
|
32
|
-
raise "Toast Error: Cannot find class method '#{@collection}' of model '#{@
|
27
|
+
unless @model.respond_to?(@collection)
|
28
|
+
raise "Toast Error: Cannot find class method '#{@collection}' of model '#{@model}', which is configured in 'acts_as_resource > collections'."
|
33
29
|
end
|
34
30
|
|
35
31
|
# FIXME: This is a lot of hallooballoo to check if the #send
|
@@ -37,26 +33,26 @@ module Toast
|
|
37
33
|
# message is not helpful to find the error.
|
38
34
|
|
39
35
|
records = if @config_out.pass_params_to.include?(@collection)
|
40
|
-
if @
|
41
|
-
raise "Toast Error: Class method '#{@collection}' of model '#{@
|
36
|
+
if @model.method(@collection).arity**2 != 1
|
37
|
+
raise "Toast Error: Class method '#{@collection}' of model '#{@model}' must accept one parameter, as configured by 'acts_as_resource > pass_params_to'."
|
42
38
|
end
|
43
39
|
# fetch results
|
44
|
-
@
|
40
|
+
@model.send(@collection, @params)
|
45
41
|
|
46
42
|
else
|
47
43
|
|
48
|
-
if @
|
49
|
-
raise "Toast Error: Class method '#{@collection}' of model '#{@
|
44
|
+
if @model.method(@collection).arity > 0
|
45
|
+
raise "Toast Error: Class method '#{@collection}' of model '#{@model}' must not accept any parameter, as configured by 'acts_as_resource'"
|
50
46
|
end
|
51
47
|
# fetch results
|
52
|
-
@
|
48
|
+
@model.send(@collection)
|
53
49
|
end
|
54
50
|
|
55
51
|
case @format
|
56
52
|
when "html"
|
57
53
|
{
|
58
|
-
:template => "resources/#{@
|
59
|
-
:locals => { @
|
54
|
+
:template => "resources/#{@model.to_s.pluralize.underscore}",
|
55
|
+
:locals => { @model.to_s.pluralize.underscore.to_sym => records }
|
60
56
|
}
|
61
57
|
when "json"
|
62
58
|
{
|
@@ -103,15 +99,7 @@ module Toast
|
|
103
99
|
|
104
100
|
begin
|
105
101
|
|
106
|
-
|
107
|
-
# post on scope?
|
108
|
-
record = @model_or_relation.new payload
|
109
|
-
hook = @config_in.before_scoped_create[@collection]
|
110
|
-
record.send(hook, @model_or_relation.proxy_association.owner) if hook
|
111
|
-
record.save!
|
112
|
-
else
|
113
|
-
record = @model_or_relation.create! payload
|
114
|
-
end
|
102
|
+
record = @model.create! payload
|
115
103
|
|
116
104
|
{
|
117
105
|
:json => record.represent( @config_out.exposed_attributes,
|
data/lib/toast/config_dsl.rb
CHANGED
@@ -14,7 +14,6 @@ module Toast
|
|
14
14
|
@deletable = false
|
15
15
|
@postable = false
|
16
16
|
@pass_params_to = []
|
17
|
-
@before_scoped_create = {}
|
18
17
|
@in_collection = ConfigDSL::InCollection.new model, self
|
19
18
|
@media_type = "application/json"
|
20
19
|
|
@@ -77,17 +76,6 @@ module Toast
|
|
77
76
|
self.pass_params_to = arg
|
78
77
|
end
|
79
78
|
|
80
|
-
def before_scoped_create= arg
|
81
|
-
for key in arg.keys
|
82
|
-
@before_scoped_create[key.to_s] = arg[key].to_sym
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def before_scoped_create arg={}
|
87
|
-
return(@before_scoped_create) if arg.empty?
|
88
|
-
self.before_scoped_create = arg
|
89
|
-
end
|
90
|
-
|
91
79
|
def collections= collections=[]
|
92
80
|
@collections = ConfigDSL.sanitize(collections, "collections")
|
93
81
|
end
|
@@ -143,7 +131,7 @@ module Toast
|
|
143
131
|
def writables *arg
|
144
132
|
self.writables = 42
|
145
133
|
end
|
146
|
-
|
134
|
+
|
147
135
|
def writables= arg
|
148
136
|
puts
|
149
137
|
puts "Toast Config Warning (#{model.class}): Defining \"writables\" in collection definition has no effect."
|
data/lib/toast/engine.rb
CHANGED
data/lib/toast/record.rb
CHANGED
@@ -34,11 +34,14 @@ module Toast
|
|
34
34
|
raise PayloadFormatError
|
35
35
|
end
|
36
36
|
|
37
|
-
# ignore
|
38
|
-
|
37
|
+
# ignore:
|
38
|
+
# * all exposed readable, but not writable fields
|
39
|
+
# * all associations
|
40
|
+
# * self
|
41
|
+
((@config_in.readables - @config_in.writables) + @config_in.exposed_associations + ["self"]).each do |rof|
|
39
42
|
payload.delete(rof)
|
40
43
|
end
|
41
|
-
|
44
|
+
|
42
45
|
# set the virtual attributes
|
43
46
|
(@config_in.writables - @record.attribute_names - @config_in.exposed_associations).each do |vattr|
|
44
47
|
|
@@ -48,10 +51,10 @@ module Toast
|
|
48
51
|
|
49
52
|
@record.send("#{vattr}=", payload.delete(vattr))
|
50
53
|
end
|
51
|
-
|
54
|
+
|
52
55
|
# mass-update for the rest
|
53
56
|
@record.update_attributes payload
|
54
|
-
{
|
57
|
+
{
|
55
58
|
:json => @record.represent( @config_out.exposed_attributes,
|
56
59
|
@config_out.exposed_associations,
|
57
60
|
@base_uri,
|
data/lib/toast/resource.rb
CHANGED
@@ -23,13 +23,13 @@ module Toast
|
|
23
23
|
id = params[:id]
|
24
24
|
subresource_name = params[:subresource]
|
25
25
|
format = params[:format]
|
26
|
-
|
26
|
+
|
27
27
|
begin
|
28
|
-
|
28
|
+
|
29
29
|
# determine model
|
30
30
|
model = get_class_by_resource_name resource_name
|
31
|
-
|
32
|
-
# determine config for representation
|
31
|
+
|
32
|
+
# determine config for representation
|
33
33
|
# config_in: cosumed representation
|
34
34
|
# config_out: produced representation
|
35
35
|
config_out = model.toast_config request.accept_media_types.prefered
|
@@ -37,9 +37,9 @@ module Toast
|
|
37
37
|
|
38
38
|
# ... or in case of an association request
|
39
39
|
config_assoc_src = model.toast_config request.headers["Assoc-source-type"] # ?
|
40
|
-
|
40
|
+
|
41
41
|
# base URI for returned object
|
42
|
-
base_uri = request.base_url + request.script_name +
|
42
|
+
base_uri = request.base_url + request.script_name +
|
43
43
|
(config_out.namespace ? "/" + config_out.namespace : "")
|
44
44
|
|
45
45
|
# decide which sub resource type
|
@@ -52,24 +52,21 @@ module Toast
|
|
52
52
|
elsif (config_assoc_src && config_assoc_src.exposed_associations.include?(subresource_name))
|
53
53
|
|
54
54
|
# determine associated model
|
55
|
-
assoc_model =
|
55
|
+
assoc_model =
|
56
56
|
model.reflect_on_all_associations.detect{|a| a.name.to_s == subresource_name}.klass
|
57
|
-
|
58
|
-
# determine config for representation of assoc. model
|
57
|
+
|
58
|
+
# determine config for representation of assoc. model
|
59
59
|
assoc_config_out = assoc_model.toast_config request.accept_media_types.prefered
|
60
60
|
assoc_config_in = assoc_model.toast_config request.media_type
|
61
|
-
|
61
|
+
|
62
62
|
# change base URI to associated record
|
63
|
-
base_uri = request.base_url + request.script_name +
|
63
|
+
base_uri = request.base_url + request.script_name +
|
64
64
|
(assoc_config_out.namespace ? "/" + assoc_config_out.namespace : "")
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
Toast::ScopedAssociation.new(model, id, subresource_name, scope, params.clone,
|
71
|
-
assoc_config_in, assoc_config_out)
|
72
|
-
end
|
66
|
+
|
67
|
+
Toast::Association.new(model, id, subresource_name, format, config_assoc_src,
|
68
|
+
assoc_model, assoc_config_in, assoc_config_out)
|
69
|
+
|
73
70
|
else
|
74
71
|
raise ResourceNotFound
|
75
72
|
end
|
@@ -77,7 +74,7 @@ module Toast
|
|
77
74
|
# set base to be prepended to URIs
|
78
75
|
rsc.base_uri = base_uri
|
79
76
|
|
80
|
-
|
77
|
+
|
81
78
|
|
82
79
|
rsc
|
83
80
|
rescue NameError
|
@@ -115,7 +112,7 @@ module Toast
|
|
115
112
|
self.delete
|
116
113
|
end
|
117
114
|
when "GET"
|
118
|
-
self.get
|
115
|
+
self.get
|
119
116
|
else
|
120
117
|
raise MethodNotAllowed
|
121
118
|
end
|
data/lib/toast/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 63
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 0.8.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "robokopp (Robert Anni\xC3\xA9s)"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-08-20 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rails
|
@@ -102,7 +102,6 @@ files:
|
|
102
102
|
- lib/toast/record.rb
|
103
103
|
- lib/toast/resource.rb
|
104
104
|
- lib/toast/single.rb
|
105
|
-
- lib/toast/scoped_association.rb
|
106
105
|
- README.md
|
107
106
|
homepage: https://github.com/robokopp/toast
|
108
107
|
licenses: []
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Toast
|
2
|
-
class ScopedAssociation < Resource
|
3
|
-
# delegeates everything to Toast::Collection, where the model is replaced
|
4
|
-
# by the Relation this association creates
|
5
|
-
|
6
|
-
def initialize(model, id, association_name, scope_name, params,
|
7
|
-
config_in, config_out)
|
8
|
-
|
9
|
-
record = model.find(id)
|
10
|
-
assoc_model = record.class
|
11
|
-
|
12
|
-
@collection = Toast::Collection.new(record.send(association_name),
|
13
|
-
scope_name,
|
14
|
-
params,
|
15
|
-
config_in,
|
16
|
-
config_out)
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
delegate :get, :put, :post, :delete, :base_uri, :base_uri=, :to => :@collection
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|