api_resource 0.6.21 → 0.6.22
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/.yardopts +1 -0
- data/Gemfile.lock +1 -1
- data/LICENSE.txt +22 -0
- data/README.md +16 -9
- data/docs/Attributes.md +64 -0
- data/docs/Caching.md +45 -0
- data/docs/GettingStarted.md +149 -0
- data/docs/Relationships.md +136 -0
- data/docs/ResourceDefinition.md +80 -0
- data/docs/Retrieval.md +279 -0
- data/docs/Serialization.md +56 -0
- data/lib/api_resource/associations/has_many_remote_object_proxy.rb +2 -2
- data/lib/api_resource/attributes.rb +16 -4
- data/lib/api_resource/base.rb +98 -19
- data/lib/api_resource/conditions/abstract_condition.rb +241 -129
- data/lib/api_resource/conditions/include_condition.rb +7 -1
- data/lib/api_resource/conditions/pagination_condition.rb +37 -0
- data/lib/api_resource/conditions/where_condition.rb +19 -0
- data/lib/api_resource/conditions.rb +18 -2
- data/lib/api_resource/connection.rb +27 -13
- data/lib/api_resource/exceptions.rb +11 -11
- data/lib/api_resource/finders/abstract_finder.rb +176 -95
- data/lib/api_resource/finders/multi_object_association_finder.rb +10 -9
- data/lib/api_resource/finders/resource_finder.rb +59 -49
- data/lib/api_resource/finders/single_finder.rb +5 -6
- data/lib/api_resource/finders/single_object_association_finder.rb +52 -51
- data/lib/api_resource/finders.rb +1 -1
- data/lib/api_resource/formats/file_upload_format.rb +75 -0
- data/lib/api_resource/formats.rb +4 -1
- data/lib/api_resource/response.rb +108 -0
- data/lib/api_resource/scopes.rb +62 -5
- data/lib/api_resource/serializer.rb +1 -1
- data/lib/api_resource/typecasters/boolean_typecaster.rb +1 -0
- data/lib/api_resource/typecasters/integer_typecaster.rb +1 -0
- data/lib/api_resource/typecasters/time_typecaster.rb +12 -4
- data/lib/api_resource/version.rb +1 -1
- data/lib/api_resource.rb +1 -0
- data/spec/lib/associations/has_one_remote_object_proxy_spec.rb +4 -4
- data/spec/lib/associations_spec.rb +3 -3
- data/spec/lib/attributes_spec.rb +16 -1
- data/spec/lib/base_spec.rb +121 -39
- data/spec/lib/conditions/{abstract_conditions_spec.rb → abstract_condition_spec.rb} +23 -11
- data/spec/lib/conditions/pagination_condition_spec.rb +88 -0
- data/spec/lib/finders/multi_object_association_finder_spec.rb +55 -27
- data/spec/lib/finders/resource_finder_spec.rb +26 -2
- data/spec/lib/finders/single_object_association_finder_spec.rb +14 -6
- data/spec/lib/finders_spec.rb +81 -81
- data/spec/lib/observing_spec.rb +3 -4
- data/spec/lib/response_spec.rb +18 -0
- data/spec/lib/scopes_spec.rb +25 -1
- data/spec/lib/typecasters/boolean_typecaster_spec.rb +1 -1
- data/spec/lib/typecasters/integer_typecaster_spec.rb +1 -1
- data/spec/lib/typecasters/time_typecaster_spec.rb +6 -0
- data/spec/support/files/bg-awesome.jpg +0 -0
- data/spec/support/mocks/test_resource_mocks.rb +26 -16
- data/spec/support/requests/test_resource_requests.rb +27 -23
- metadata +24 -4
@@ -1,133 +1,245 @@
|
|
1
1
|
module ApiResource
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
3
|
+
module Conditions
|
4
|
+
|
5
|
+
class AbstractCondition
|
6
|
+
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# @!attribute [r] association
|
10
|
+
# @return [Boolean] Are we an association?
|
11
|
+
attr_reader :association
|
12
|
+
|
13
|
+
# @!attribute [r] conditions
|
14
|
+
# @return [Hash] Hash of conditions
|
15
|
+
attr_reader :conditions
|
16
|
+
|
17
|
+
# @!attribute [r] included_objects
|
18
|
+
# @return [Array<Symbol>] List of associations to eager load
|
19
|
+
attr_reader :included_objects
|
20
|
+
|
21
|
+
# @!attribute [r] internal_object
|
22
|
+
# @return [Array<ApiResource::Base>] Underlying objects we found
|
23
|
+
attr_reader :internal_object
|
24
|
+
|
25
|
+
# @!attribute [r] klass
|
26
|
+
# @return [Class] Owner class
|
27
|
+
attr_reader :klass
|
28
|
+
|
29
|
+
# @!attribute [r] remote_path
|
30
|
+
# @return [String] Path to hit when we find stuff
|
31
|
+
attr_reader :remote_path
|
32
|
+
|
33
|
+
# TODO: add the other load forcing methods here for collections
|
34
|
+
delegate :[], :[]=, :<<, :first, :second, :last, :blank?, :nil?,
|
35
|
+
:include?, :push, :pop, :+, :concat, :flatten, :flatten!, :compact,
|
36
|
+
:compact!, :empty?, :fetch, :map, :reject, :reject!, :reverse,
|
37
|
+
:select, :select!, :size, :sort, :sort!, :uniq, :uniq!, :to_a,
|
38
|
+
:sample, :slice, :slice!, :count, :present?, :delete_if,
|
39
|
+
:to => :internal_object
|
40
|
+
|
41
|
+
# need to figure out what to do with args in the subclass,
|
42
|
+
# parent is the set of scopes we have right now
|
43
|
+
def initialize(args, klass)
|
44
|
+
@klass = klass
|
45
|
+
@conditions = args.with_indifferent_access
|
46
|
+
@klass.load_resource_definition
|
47
|
+
end
|
48
|
+
|
49
|
+
def all(*args)
|
50
|
+
if args.blank?
|
51
|
+
self.internal_object
|
52
|
+
else
|
53
|
+
self.find(*([:all] + args))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Is this a find without any conditions
|
59
|
+
#
|
60
|
+
# @return [Boolean]
|
61
|
+
def blank_conditions?
|
62
|
+
self.conditions.blank?
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Accessor for the current page if we
|
67
|
+
# are paginated. Returns 1 if we are not
|
68
|
+
# paginated or have an invalid page
|
69
|
+
#
|
70
|
+
# @return [Fixnum] [description]
|
71
|
+
def current_page
|
72
|
+
return 1 unless self.paginated?
|
73
|
+
return 1 if @conditions[:page].to_i < 1
|
74
|
+
return @conditions[:page].to_i
|
75
|
+
end
|
76
|
+
|
77
|
+
def each(&block)
|
78
|
+
self.internal_object.each(&block)
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Are we set up to eager load associations?
|
83
|
+
#
|
84
|
+
# @return [Boolean]
|
85
|
+
def eager_load?
|
86
|
+
self.included_objects.present?
|
87
|
+
end
|
88
|
+
|
89
|
+
def expires_in(time)
|
90
|
+
ApiResource::Decorators::CachingDecorator.new(self, time)
|
91
|
+
end
|
92
|
+
|
93
|
+
# implement find that accepts an optional
|
94
|
+
# condition object
|
95
|
+
def find(*args)
|
96
|
+
self.klass.find(*(args + [self]))
|
97
|
+
end
|
98
|
+
|
99
|
+
def included_objects
|
100
|
+
Array.wrap(@included_objects)
|
101
|
+
end
|
102
|
+
|
103
|
+
def internal_object
|
104
|
+
return @internal_object if @loaded
|
105
|
+
@internal_object = self.instantiate_finder
|
106
|
+
@internal_object.load
|
107
|
+
@loaded = true
|
108
|
+
@internal_object
|
109
|
+
end
|
110
|
+
|
111
|
+
# TODO: review the hierarchy that makes this necessary
|
112
|
+
# consider changing it to alias method
|
113
|
+
def load
|
114
|
+
self.internal_object
|
115
|
+
end
|
116
|
+
|
117
|
+
def loaded?
|
118
|
+
@loaded == true
|
119
|
+
end
|
120
|
+
|
121
|
+
# TODO: Remove the bang, this doesn't modify anything
|
122
|
+
def merge!(cond)
|
123
|
+
|
124
|
+
# merge included objects
|
125
|
+
@included_objects = self.included_objects | cond.included_objects
|
126
|
+
|
127
|
+
# handle pagination
|
128
|
+
if cond.paginated?
|
129
|
+
@paginated = true
|
130
|
+
end
|
131
|
+
|
132
|
+
# merge conditions
|
133
|
+
@conditions = @conditions.merge(cond.to_hash)
|
134
|
+
|
135
|
+
# handle associations
|
136
|
+
if cond.association
|
137
|
+
@association = true
|
138
|
+
end
|
139
|
+
# handle remote path copying
|
140
|
+
@remote_path ||= cond.remote_path
|
141
|
+
|
142
|
+
return self
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# The offset we are currently at in our query
|
147
|
+
# Returns 0 if we are not paginated
|
148
|
+
#
|
149
|
+
# @return [Fixnum]
|
150
|
+
def offset
|
151
|
+
return 0 unless self.paginated?
|
152
|
+
prev_page = self.current_page.to_i - 1
|
153
|
+
prev_page * self.per_page
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Reader for whether or not we are paginated
|
158
|
+
#
|
159
|
+
# @return [Boolean]
|
160
|
+
def paginated?
|
161
|
+
@paginated
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
# Number of records per page if paginated
|
166
|
+
# Returns 1 if number is out of range or if pagination
|
167
|
+
# is not enabled
|
168
|
+
#
|
169
|
+
# @return [Fixnum]
|
170
|
+
def per_page
|
171
|
+
return 1 unless self.paginated?
|
172
|
+
return 1 if @conditions["per_page"].to_i < 1
|
173
|
+
return @conditions["per_page"].to_i
|
174
|
+
end
|
175
|
+
|
176
|
+
def reload
|
177
|
+
if instance_variable_defined?(:@internal_object)
|
178
|
+
remove_instance_variable(:@internal_object)
|
179
|
+
end
|
180
|
+
@loaded = false
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_query
|
184
|
+
CGI.unescape(to_query_safe_hash(self.to_hash).to_query)
|
185
|
+
end
|
186
|
+
|
187
|
+
def to_hash
|
188
|
+
self.conditions.to_hash
|
189
|
+
end
|
190
|
+
|
191
|
+
#
|
192
|
+
# Total number of records found in the collection
|
193
|
+
# if it is paginated
|
194
|
+
#
|
195
|
+
# @return [Fixnum]
|
196
|
+
def total_entries
|
197
|
+
self.internal_object.total_entries
|
198
|
+
end
|
199
|
+
|
200
|
+
#
|
201
|
+
# The total number of pages in our collection
|
202
|
+
# or 1 if it is not paginated
|
203
|
+
#
|
204
|
+
# @return [Fixnum]
|
205
|
+
def total_pages
|
206
|
+
return 1 unless self.paginated?
|
207
|
+
return (self.total_entries / self.per_page.to_f).ceil
|
208
|
+
end
|
209
|
+
|
210
|
+
protected
|
211
|
+
|
212
|
+
#
|
213
|
+
# Proxy all calls to the base finder class
|
214
|
+
# @param sym [Symbol] Method name
|
215
|
+
# @param *args [Array<Mixed>] Args
|
216
|
+
# @param &block [Proc] Block
|
217
|
+
#
|
218
|
+
# @return [Mixed]
|
219
|
+
def method_missing(sym, *args, &block)
|
220
|
+
result = @klass.send(sym, *args, &block)
|
221
|
+
|
222
|
+
if result.is_a?(ApiResource::Conditions::AbstractCondition)
|
223
|
+
return self.dup.merge!(result)
|
224
|
+
else
|
225
|
+
return result
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def instantiate_finder
|
230
|
+
ApiResource::Finders::ResourceFinder.new(self.klass, self)
|
231
|
+
end
|
232
|
+
|
233
|
+
def to_query_safe_hash(hash)
|
234
|
+
hash.each_pair do |k,v|
|
235
|
+
hash[k] = to_query_safe_hash(v) if v.is_a?(Hash)
|
236
|
+
hash[k] = true if v == {}
|
237
|
+
end
|
238
|
+
return hash
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
132
244
|
|
133
245
|
end
|
@@ -4,7 +4,13 @@ module ApiResource
|
|
4
4
|
|
5
5
|
class IncludeCondition < AbstractCondition
|
6
6
|
|
7
|
-
|
7
|
+
#
|
8
|
+
# Constructor
|
9
|
+
#
|
10
|
+
# @param klass [Class] Finder
|
11
|
+
# @param incs [Array<Symbol>, Symbol] Associations to include
|
12
|
+
#
|
13
|
+
def initialize(klass, incs)
|
8
14
|
super({}, klass)
|
9
15
|
@included_objects = Array.wrap(incs)
|
10
16
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ApiResource
|
2
|
+
|
3
|
+
module Conditions
|
4
|
+
|
5
|
+
#
|
6
|
+
# Class to handle pagination params, passing
|
7
|
+
# of pagination params along to the server, and the
|
8
|
+
# retrieval of the headers from the response
|
9
|
+
#
|
10
|
+
# @author [dlangevin]
|
11
|
+
#
|
12
|
+
class PaginationCondition < AbstractCondition
|
13
|
+
|
14
|
+
#
|
15
|
+
# Constructor - sets up the pagination options
|
16
|
+
# @param opts = {} [Hash] Pagination opts
|
17
|
+
# @option opts [Fixnum] :page (1) Page we are on
|
18
|
+
# @option opts [Fixnum] :per_page (10) Number per page
|
19
|
+
def initialize(klass, opts = {})
|
20
|
+
@page = opts[:page] || 1
|
21
|
+
@per_page = opts[:per_page] || 10
|
22
|
+
super({ page: @page, per_page: @per_page }, klass)
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Are we paginated?
|
27
|
+
#
|
28
|
+
# @return [Boolean] true
|
29
|
+
def paginated?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ApiResource
|
2
|
+
|
3
|
+
module Conditions
|
4
|
+
|
5
|
+
#
|
6
|
+
# Class to handle pagination params, passing
|
7
|
+
# of pagination params along to the server, and the
|
8
|
+
# retrieval of the headers from the response
|
9
|
+
#
|
10
|
+
# @author [dlangevin]
|
11
|
+
#
|
12
|
+
class WhereCondition < AbstractCondition
|
13
|
+
def initialize(klass, opts)
|
14
|
+
super(opts, klass)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -7,10 +7,12 @@ module ApiResource
|
|
7
7
|
|
8
8
|
autoload :AbstractCondition
|
9
9
|
autoload :AssociationCondition
|
10
|
-
autoload :SingleObjectAssociationCondition
|
11
|
-
autoload :MultiObjectAssociationCondition
|
12
10
|
autoload :IncludeCondition
|
11
|
+
autoload :MultiObjectAssociationCondition
|
12
|
+
autoload :PaginationCondition
|
13
|
+
autoload :SingleObjectAssociationCondition
|
13
14
|
autoload :ScopeCondition
|
15
|
+
autoload :WhereCondition
|
14
16
|
|
15
17
|
module ClassMethods
|
16
18
|
|
@@ -30,6 +32,20 @@ module ApiResource
|
|
30
32
|
|
31
33
|
end
|
32
34
|
|
35
|
+
def paginate(opts = {})
|
36
|
+
self.load_resource_definition
|
37
|
+
|
38
|
+
# Everything looks good so just create the scope
|
39
|
+
ApiResource::Conditions::PaginationCondition.new(self, opts)
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def where(opts = {})
|
44
|
+
self.load_resource_definition
|
45
|
+
|
46
|
+
ApiResource::Conditions::WhereCondition.new(self, opts)
|
47
|
+
end
|
48
|
+
|
33
49
|
end
|
34
50
|
|
35
51
|
end
|
@@ -62,17 +62,28 @@ module ApiResource
|
|
62
62
|
headers = build_request_headers(headers, :get, site)
|
63
63
|
|
64
64
|
self.with_caching(path, headers) do
|
65
|
-
|
65
|
+
request(:get, path, {}, headers)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
def delete(path, headers = self.headers)
|
70
|
-
request(
|
70
|
+
request(
|
71
|
+
:delete,
|
72
|
+
path,
|
73
|
+
{},
|
74
|
+
build_request_headers(headers, :delete, self.site.merge(path))
|
75
|
+
)
|
71
76
|
return true
|
72
77
|
end
|
73
78
|
|
74
79
|
def head(path, headers = self.headers)
|
75
|
-
request(
|
80
|
+
request(
|
81
|
+
:head,
|
82
|
+
path,
|
83
|
+
{},
|
84
|
+
build_request_headers(headers, :head, self.site.merge(path))
|
85
|
+
)
|
86
|
+
return true
|
76
87
|
end
|
77
88
|
|
78
89
|
# make a put request
|
@@ -97,7 +108,7 @@ module ApiResource
|
|
97
108
|
"[DEPRECATION] Returning a response body from a PUT " +
|
98
109
|
"is deprecated. \n#{response.pretty_inspect} was returned."
|
99
110
|
)
|
100
|
-
return
|
111
|
+
return response
|
101
112
|
end
|
102
113
|
end
|
103
114
|
|
@@ -107,13 +118,11 @@ module ApiResource
|
|
107
118
|
# have a timeout, general exception, or
|
108
119
|
# if result.code is not within 200..399
|
109
120
|
def post(path, body = {}, headers = self.headers)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
build_request_headers(headers, :post, self.site.merge(path))
|
116
|
-
)
|
121
|
+
request(
|
122
|
+
:post,
|
123
|
+
path,
|
124
|
+
format.encode(body),
|
125
|
+
build_request_headers(headers, :post, self.site.merge(path))
|
117
126
|
)
|
118
127
|
end
|
119
128
|
|
@@ -171,7 +180,12 @@ module ApiResource
|
|
171
180
|
ApiResource.logger.error(error.message)
|
172
181
|
result = error.response
|
173
182
|
else
|
174
|
-
|
183
|
+
exception = ApiResource::ConnectionError.new(
|
184
|
+
nil,
|
185
|
+
:message => "Unknown error #{error}"
|
186
|
+
)
|
187
|
+
exception.set_backtrace(error.backtrace)
|
188
|
+
raise exception
|
175
189
|
end
|
176
190
|
end
|
177
191
|
return propogate_response_or_error(result, result.code)
|
@@ -182,7 +196,7 @@ module ApiResource
|
|
182
196
|
when 301,302
|
183
197
|
raise ApiResource::Redirection.new(response)
|
184
198
|
when 200..399
|
185
|
-
response
|
199
|
+
return ApiResource::Response.new(response)
|
186
200
|
when 400
|
187
201
|
raise ApiResource::BadRequest.new(response)
|
188
202
|
when 401
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module ApiResource
|
2
2
|
class ConnectionError < StandardError # :nodoc:
|
3
|
-
|
3
|
+
|
4
4
|
cattr_accessor :http_code
|
5
|
-
|
5
|
+
|
6
6
|
attr_reader :response
|
7
7
|
|
8
8
|
def initialize(response, options = {})
|
@@ -15,9 +15,9 @@ module ApiResource
|
|
15
15
|
message = "Failed."
|
16
16
|
|
17
17
|
if response.respond_to?(:code)
|
18
|
-
message << " Response code = #{response.code}."
|
18
|
+
message << " Response code = #{response.code}."
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
if response.respond_to?(:body)
|
22
22
|
begin
|
23
23
|
body = JSON.parse(response.body).pretty_inspect
|
@@ -26,15 +26,15 @@ module ApiResource
|
|
26
26
|
end
|
27
27
|
message << "\nResponse message = #{body}."
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
message << "\n#{@message}"
|
31
31
|
message << "\n#{@path}"
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def http_code
|
35
35
|
self.class.http_code
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
end
|
39
39
|
|
40
40
|
# Raised when a Timeout::Error occurs.
|
@@ -72,7 +72,7 @@ module ApiResource
|
|
72
72
|
|
73
73
|
# 404 Not Found
|
74
74
|
class ResourceNotFound < ClientError; self.http_code = 404; end # :nodoc:
|
75
|
-
|
75
|
+
|
76
76
|
# 406 Not Acceptable
|
77
77
|
class NotAcceptable < ClientError; self.http_code = 406; end
|
78
78
|
|
@@ -81,7 +81,7 @@ module ApiResource
|
|
81
81
|
|
82
82
|
# 410 Gone
|
83
83
|
class ResourceGone < ClientError; self.http_code = 410; end # :nodoc:
|
84
|
-
|
84
|
+
|
85
85
|
class UnprocessableEntity < ClientError; self.http_code = 422; end
|
86
86
|
|
87
87
|
# 5xx Server Error
|
@@ -89,9 +89,9 @@ module ApiResource
|
|
89
89
|
|
90
90
|
# 405 Method Not Allowed
|
91
91
|
class MethodNotAllowed < ClientError # :nodoc:
|
92
|
-
|
92
|
+
|
93
93
|
self.http_code = 405
|
94
|
-
|
94
|
+
|
95
95
|
def allowed_methods
|
96
96
|
@response['Allow'].split(',').map { |verb| verb.strip.downcase.to_sym }
|
97
97
|
end
|