toast 0.7.5 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|