toast 0.9.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,175 +0,0 @@
1
- module Toast
2
-
3
- class ResourceNotFound < Exception; end
4
- class MethodNotAllowed < Exception; end
5
- class PayloadInvalid < Exception; end
6
- class Conflict < Exception; end
7
- class PayloadFormatError < Exception; end
8
- class UnsupportedMediaType < Exception; end
9
- class RequestedVersionNotDefined < Exception; end
10
- class ResourceNotAcceptable < Exception; end
11
- class BadRequest < Exception; end
12
-
13
- # Represents a resource. There are following resource types as sub classes:
14
- # Record, Collection, Association, Single
15
- class Resource
16
-
17
- attr_accessor :prefered_media_type, :base_uri, :payload_content_type
18
-
19
- def initialize
20
- raise 'ToastResource#new: use #build to create an instance'
21
- end
22
-
23
- def self.build params, request
24
- resource_name = params[:resource]
25
- id = params[:id]
26
- subresource_name = params[:subresource]
27
- format = params[:format]
28
-
29
- begin
30
-
31
- # determine model
32
- model = get_class_by_resource_name resource_name
33
-
34
- # determine config for representation
35
- # config_in: cosumed representation
36
- # config_out: produced representation
37
- config_out = model.toast_config request.accept_media_types.prefered
38
- config_in = model.toast_config request.media_type
39
-
40
- # ... or in case of an association request
41
- config_assoc_src = model.toast_config request.headers["Assoc-source-type"] # ?
42
-
43
- # base URI for returned object
44
- base_uri = request.base_url + request.script_name +
45
- (config_out.namespace ? "/" + config_out.namespace : "")
46
-
47
- # decide which sub resource type
48
- rsc = if id.nil? and config_out.singles.include?(subresource_name)
49
- Toast::Single.new(model, subresource_name, params.clone, config_in, config_out)
50
- elsif id.nil?
51
- Toast::Collection.new(model, subresource_name, params.clone, config_in, config_out)
52
- elsif subresource_name.nil?
53
- Toast::Record.new(model, id, format, params.clone, config_in, config_out)
54
- elsif (config_assoc_src && config_assoc_src.exposed_associations.include?(subresource_name))
55
-
56
- # determine associated model
57
- assoc_model =
58
- model.reflect_on_all_associations.detect{|a| a.name.to_s == subresource_name}.klass
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
-
69
- Toast::Association.new(model, id, subresource_name, params.clone, format, config_assoc_src,
70
- assoc_model, assoc_config_in, assoc_config_out)
71
-
72
- else
73
- raise ResourceNotFound
74
- end
75
-
76
- # set base to be prepended to URIs
77
- rsc.base_uri = base_uri
78
-
79
-
80
-
81
- rsc
82
- rescue NameError
83
- raise ResourceNotFound
84
- end
85
- end
86
-
87
- def self.get_class_by_resource_name name
88
- begin
89
- model = name.singularize.classify.constantize # raises NameError
90
-
91
- unless ((model.superclass == ActiveRecord::Base) and model.is_resourceful_model?)
92
- raise ResourceNotFound
93
- end
94
-
95
- model
96
-
97
- rescue NameError
98
- raise ResourceNotFound
99
- end
100
- end
101
-
102
- def apply method, payload, payload_media_type, link_path_info
103
- case method
104
- when "PUT","POST"
105
- if link_path_info
106
- self.link link_path_info
107
- else
108
- self.send(method.downcase, payload, payload_media_type)
109
- end
110
- when "DELETE"
111
- if link_path_info
112
- self.unlink link_path_info
113
- else
114
- self.delete
115
- end
116
- when "GET"
117
- self.get
118
- else
119
- raise MethodNotAllowed
120
- end
121
- end
122
-
123
- private
124
- def uri_fields record, in_collection=false
125
- out = {}
126
-
127
- exposed_assoc =
128
- in_collection ? record.class.toast_config.in_collection.exposed_associations :
129
- record.class.toast_config.exposed_associations
130
-
131
- exposed_assoc.each do |assoc|
132
- out[assoc] = "#{self.base_uri}#{record.uri_path}/#{assoc}"
133
- end
134
-
135
- out["self"] = self.base_uri + record.uri_path
136
-
137
- out
138
- end
139
-
140
-
141
- def paginate_query config, relation_name, relation, params
142
-
143
- if pagination = config.paginations[relation_name] and params[:page] =~ /\d+/
144
-
145
- raise Toast::BadRequest.new("Page 0 not defined. Paging starts with 1") if params[:page].to_i == 0
146
-
147
- ps = pagination[:page_size].to_i
148
- total = relation.count
149
-
150
- page = params[:page].to_i
151
- total_pages = (total/ps) + (total%ps == 0 ? 0 : 1)
152
-
153
- pagination_info = {:total => total}
154
-
155
- if total_pages > 0
156
-
157
- if page > total_pages
158
- pagination_info[:prev] = total_pages
159
- else
160
- pagination_info[:prev] = page - 1 unless page == 1
161
- pagination_info[:next] = page + 1 if page < total_pages
162
- end
163
-
164
- pagination_info[:last] = total_pages
165
- else
166
- pagination_info[:last] = 1
167
- end
168
-
169
- [relation.limit(ps).offset((page-1) * ps), pagination_info]
170
- else
171
- [relation, nil]
172
- end
173
- end
174
- end
175
- end
data/lib/toast/single.rb DELETED
@@ -1,89 +0,0 @@
1
- module Toast
2
-
3
- # A Single resource is queried without an ID, by custom class methods
4
- # or scopes of the model or ActiveRecord single finders like:
5
- # first, last
6
-
7
- # The single resource name must be a class method of the model and
8
- # must return nil or an instance.
9
-
10
- # GET is the only allowed verb. To make changes the URI with ID has
11
- # to be used.
12
- class Single < Resource
13
-
14
- attr_reader :model
15
-
16
- def initialize model, subresource_name, params, config_in, config_out
17
- @config_in = config_in
18
- @config_out = config_out
19
-
20
- unless @config_out.singles.include? subresource_name
21
- raise ResourceNotFound
22
- end
23
-
24
- @model = model
25
- @params = params
26
- @format = params[:format]
27
-
28
- unless @model.respond_to?(subresource_name)
29
- raise "Toast Error: Cannot find class method '#{@model}.#{subresource_name}', which is configured in 'acts_as_resource > singles'."
30
- end
31
-
32
- @record = if @config_out.pass_params_to.include?(subresource_name)
33
- if @model.method(subresource_name).arity != 1
34
- raise "Toast Error: Class method '#{@model}.#{subresource_name}' must accept one parameter, as configured by 'acts_as_resource > pass_params_to'."
35
- end
36
- @model.send(subresource_name, @params)
37
- else
38
- if(@model.method(subresource_name).arity < -1 or
39
- @model.method(subresource_name).arity > 0)
40
- raise "Toast Error: Class method '#{@model}.#{subresource_name}' must be callable w/o parameters"
41
- end
42
- @model.send(subresource_name)
43
- end
44
-
45
- raise ResourceNotFound if @record.nil?
46
- end
47
-
48
- def get
49
- case @format
50
- when "html"
51
- {
52
- :template => "resources/#{model.to_s.underscore}",
53
- :locals => { model.to_s.pluralize.underscore.to_sym => @record }
54
- }
55
- when "json"
56
- {
57
- :json => @record.represent( @config_out.exposed_attributes,
58
- @config_out.exposed_associations,
59
- @base_uri,
60
- @config_out.media_type),
61
- :status => :ok
62
- }
63
- else
64
- raise ResourceNotFound
65
- end
66
- end
67
-
68
-
69
- def put
70
- raise MethodNotAllowed
71
- end
72
-
73
- def post payload
74
- raise MethodNotAllowed
75
- end
76
-
77
- def delete
78
- raise MethodNotAllowed
79
- end
80
-
81
- def link l
82
- raise MethodNotAllowed
83
- end
84
-
85
- def unlink l
86
- raise MethodNotAllowed
87
- end
88
- end
89
- end