restfulness 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ddaa3efca8063cce4459e78242665f30c7aa7beb
4
- data.tar.gz: 39fc6f40248c0a0453ce566fc97537920977e529
3
+ metadata.gz: 656fc9b27618b6b00f0cdc31dff51fc59081881b
4
+ data.tar.gz: eed7ea6153eb14c67d0888643287ed911bfb477a
5
5
  SHA512:
6
- metadata.gz: 205f618a6e3d7968e9e365e5a90abbbe335ebc994179da9030bc6d57d2bcafacfa9b001f612beea36490e18a2ed8344a2e19e772d70071b266500ba31832b7ec
7
- data.tar.gz: f2c6c07d14351f6f05e270f34df4b23b08dea402a82b0988cc8ed4076d960d379b88c1bc2384ebcfcb9b7b80c372d681a790558d40b241b09bd5c3fea4ca9a11
6
+ metadata.gz: d06a2ee69944bfd705f22516c246ec49293488e69bc7bc5f7357cbe3830ac1b283e5e5046063c4e22e427d5ddf2541811c2d49b0e285eb742c63c0f132b64564
7
+ data.tar.gz: b297d63290e7df33142641c2c8d072d97bb4494ece946b8ec6f2ddb4c44e10ac6cd997729689ede5fefb299f492c77b74e82b9646f04793ca49f77c473a99e70
data/README.md CHANGED
@@ -27,7 +27,7 @@ module Twitter
27
27
  end
28
28
 
29
29
  desc "Return a personal timeline."
30
- get :home_timeline do
30
+ get :home_timeline do
31
31
  authenticate!
32
32
  current_user.statuses.limit(20)
33
33
  end
@@ -128,8 +128,6 @@ run Rack::URLMap.new(
128
128
  )
129
129
  ```
130
130
 
131
- By default, Restfulness comes with a Rack compatible dispatcher, but in the future it might make sense to add others.
132
-
133
131
  If you want to run Restfulness standalone, simply create a `config.ru` that will load up your application:
134
132
 
135
133
  ```ruby
@@ -143,7 +141,7 @@ You can then run this with rackup:
143
141
  bundle exec rackup
144
142
  ```
145
143
 
146
- For an example, checkout the `/example` directory in the source code.
144
+ For a very simple example project, checkout the `/example` directory in the source code.
147
145
 
148
146
 
149
147
  ### Routes
@@ -179,6 +177,7 @@ Resources are like Controllers in a Rails project. They handle the basic HTTP ac
179
177
  * `get`
180
178
  * `head`
181
179
  * `post`
180
+ * `patch`
182
181
  * `put`
183
182
  * `delete`
184
183
  * `options` - this is the only action provded by default
@@ -192,8 +191,8 @@ class ProjectResource < Restfulness::Resource
192
191
  project
193
192
  end
194
193
 
195
- # Update the object
196
- def put
194
+ # Update the existing object with some new attributes
195
+ def patch
197
196
  project.update(params)
198
197
  end
199
198
 
@@ -290,11 +289,99 @@ request.body # "{'key':'value'}" - string payload
290
289
  request.params # {'key' => 'value'} - usually a JSON deserialized object
291
290
  ```
292
291
 
292
+ ## Error Handling
293
+
294
+ If you want your application to return anything other than a 200 (or 202) status, you have a couple of options that allow you to send codes back to the client.
295
+
296
+ The easiest method is probably just to update the `response` code. Take the following example where we set a 403 response and the model's errors object in the payload:
297
+
298
+ ```ruby
299
+ class ProjectResource < Restfulness::Resource
300
+ def patch
301
+ if project.update_attributes(request.params)
302
+ project
303
+ else
304
+ response.status = 403
305
+ project.errors
306
+ end
307
+ end
308
+ end
309
+ ```
310
+
311
+ The favourite method in Restfulness however is to use the `HTTPException` class and helper methods that will raise the error for you. For example:
312
+
313
+ ```ruby
314
+ class ProjectResource < Restfulness::Resource
315
+ def patch
316
+ unless project.update_attributes(request.params)
317
+ forbidden!(project.errors)
318
+ end
319
+ project
320
+ end
321
+ end
322
+ ```
323
+
324
+ The `forbidden!` bang method will call the `error!` method, which in turn will raise an `HTTPException` with the appropriate status code. Exceptions are permitted to include a payload also, so you could override the `error!` method if you wished with code that will automatically re-format the payload. Another example:
325
+
326
+ ```ruby
327
+ # Regular resource
328
+ class ProjectResource < ApplicationResource
329
+ def patch
330
+ unless project.update_attributes(request.params)
331
+ forbidden!(project) # only send the project object!
332
+ end
333
+ project
334
+ end
335
+ end
336
+
337
+ # Main Application Resource
338
+ class ApplicationResource < Restfulness::Resource
339
+ # Overwrite the regular error handler so we can provide
340
+ # our own format.
341
+ def error!(status, payload = "", opts = {})
342
+ case payload
343
+ when ActiveRecord::Base # or your favourite ORM
344
+ payload = {
345
+ :errors => payload.errors.full_messages
346
+ }
347
+ end
348
+ super(status, payload, opts)
349
+ end
350
+ end
351
+
352
+ ```
353
+
354
+ This can be a really nice way to mold your errors into a standard format. All HTTP exceptions generated inside resources will pass through `error!`, even those that a triggered by a callback. It gives a great way to provide your own more complete result, or even just resort to a simple string.
355
+
356
+ The currently built in error methods are:
357
+
358
+ * `not_modified!`
359
+ * `bad_request!`
360
+ * `unauthorized!`
361
+ * `payment_required!`
362
+ * `forbidden!`
363
+ * `resource_not_found!`
364
+ * `request_timeout!`
365
+ * `conflict!`
366
+ * `gone!`
367
+ * `unprocessable_entity!`
368
+
369
+ If you'd like to see me more, please send us a pull request! Failing that, you can create your own by writing something along the lines of:
370
+
371
+ ```ruby
372
+ def im_a_teapot!(payload = "")
373
+ error!(418, payload)
374
+ end
375
+ ```
376
+
377
+
293
378
  ## Caveats and TODOs
294
379
 
295
380
  Restfulness is still very much a work in progress. Here is a list of things that we'd like to improve or fix:
296
381
 
297
- * Support for more serializers, not just JSON.
382
+ * Support for more serializers and content types, not just JSON.
383
+ * Support path methods for automatic URL generation.
384
+ * Support redirect exceptions.
298
385
  * Reloading is a PITA (see note below).
299
386
  * Needs more functional testing.
300
387
  * Support for before and after filters in resources, although I'm slightly aprehensive about this.
@@ -335,6 +422,10 @@ Restfulness was created by Sam Lown <me@samlown.com> as a solution for building
335
422
 
336
423
  ## History
337
424
 
425
+ ### 0.2.0 - October 17, 2013
426
+
427
+ Refactoring error handling and reporting so that it is easier to use and simpler.
428
+
338
429
  ### 0.1.0 - October 16, 2013
339
430
 
340
431
  First release!
data/example/README.md CHANGED
@@ -33,7 +33,7 @@ Curl is your friend!
33
33
  curl -v http://localhost:9292/projects
34
34
 
35
35
  # Try updating it
36
- curl -v -X PUT http://localhost:9292/project/project1 -H "Content-Type: application/json" -d "{\"name\":\"First Updated Project\"}"
36
+ curl -v -X PATCH http://localhost:9292/project/project1 -H "Content-Type: application/json" -d "{\"name\":\"First Updated Project\"}"
37
37
 
38
38
  # Finally remove it and check the list is empty
39
39
  curl -v -X DELETE http://localhost:9292/project/project1
data/example/app.rb CHANGED
@@ -15,7 +15,7 @@ class ProjectResource < Restfulness::Resource
15
15
  def post
16
16
  $projects << Project.new(request.params)
17
17
  end
18
- def put
18
+ def patch
19
19
  project.update(request.params)
20
20
  end
21
21
  def delete
data/lib/restfulness.rb CHANGED
@@ -8,6 +8,9 @@ require 'rack/utils'
8
8
  require 'rack/showexceptions'
9
9
  require 'rack/builder'
10
10
 
11
+
12
+ require "restfulness/resources/events"
13
+
11
14
  require "restfulness/application"
12
15
  require "restfulness/dispatcher"
13
16
  require "restfulness/exceptions"
@@ -11,27 +11,12 @@ module Restfulness
11
11
  request = Request.new(app)
12
12
  prepare_request(env, rack_req, request)
13
13
 
14
-
15
14
  # Prepare a suitable response
16
15
  response = Response.new(request)
17
16
  response.run
18
17
 
19
-
20
- # No need to provide an empty response
21
- log_response(response.code)
22
- [response.code, response.headers, [response.payload || ""]]
23
-
24
- rescue HTTPException => e
25
- log_response(e.code)
26
- [e.code, {}, [e.payload || ""]]
27
-
28
- #rescue Exception => e
29
- # log_response(500)
30
- # puts
31
- # puts e.message
32
- # puts e.backtrace
33
- # # Something unknown went wrong
34
- # [500, {}, [STATUSES[500]]]
18
+ log_response(response.status)
19
+ [response.status, response.headers, [response.payload || ""]]
35
20
  end
36
21
 
37
22
  protected
@@ -60,6 +45,8 @@ module Restfulness
60
45
  :post
61
46
  when 'PUT'
62
47
  :put
48
+ when 'PATCH'
49
+ :patch
63
50
  when 'OPTIONS'
64
51
  :options
65
52
  else
@@ -67,8 +54,8 @@ module Restfulness
67
54
  end
68
55
  end
69
56
 
70
- def log_response(code)
71
- logger.info("Completed #{code} #{STATUSES[code]}")
57
+ def log_response(status)
58
+ logger.info("Completed #{status} #{STATUSES[status]}")
72
59
  end
73
60
 
74
61
  def prepare_headers(env)
@@ -3,13 +3,13 @@ module Restfulness
3
3
 
4
4
  class HTTPException < ::StandardError
5
5
 
6
- attr_accessor :code, :payload, :headers
6
+ attr_accessor :status, :payload, :headers
7
7
 
8
- def initialize(code, payload = nil, opts = {})
9
- @code = code
8
+ def initialize(status, payload = "", opts = {})
9
+ @status = status
10
10
  @payload = payload
11
- @headers = opts[:headers]
12
- super(opts[:message] || STATUSES[code])
11
+ @headers = opts[:headers] || {}
12
+ super(opts[:message] || STATUSES[status])
13
13
  end
14
14
 
15
15
  end
@@ -71,7 +71,7 @@ module Restfulness
71
71
  end
72
72
  end
73
73
 
74
- [:get, :post, :put, :delete, :head, :options].each do |m|
74
+ [:get, :post, :put, :patch, :delete, :head, :options].each do |m|
75
75
  define_method("#{m}?") do
76
76
  action == m
77
77
  end
@@ -1,6 +1,7 @@
1
1
  module Restfulness
2
2
 
3
3
  class Resource
4
+ include Resources::Events
4
5
 
5
6
  attr_reader :request, :response
6
7
 
@@ -18,6 +19,8 @@ module Restfulness
18
19
  end
19
20
 
20
21
  def call
22
+ # At some point, we might add custom callbacks here. If you really need them though,
23
+ # you can wrap around the call method easily.
21
24
  send(request.action)
22
25
  end
23
26
 
@@ -49,14 +52,14 @@ module Restfulness
49
52
 
50
53
  def check_callbacks
51
54
  # Access control
52
- raise HTTPException.new(405) unless method_allowed?
53
- raise HTTPException.new(401) unless authorized?
54
- raise HTTPException.new(403) unless allowed?
55
+ method_not_allowed! unless method_allowed?
56
+ unauthorized! unless authorized?
57
+ forbidden! unless allowed?
55
58
 
56
59
  # The following callbacks only make sense for certain methods
57
60
  if [:head, :get, :put, :delete].include?(request.action)
58
61
 
59
- raise HTTPException.new(404) unless exists?
62
+ resource_not_found! unless exists?
60
63
 
61
64
  if [:get, :head].include?(request.action)
62
65
  # Resource status
@@ -66,26 +69,18 @@ module Restfulness
66
69
  end
67
70
  end
68
71
 
69
- ##
70
-
71
-
72
72
  protected
73
73
 
74
- def error(code, payload = nil, opts = {})
75
- raise HTTPException.new(code, payload, opts)
76
- end
77
-
78
74
  def logger
79
75
  Restfulness.logger
80
76
  end
81
77
 
82
-
83
78
  private
84
79
 
85
80
  def check_if_modified
86
81
  date = request.headers[:if_modified_since]
87
82
  if date && date == last_modified.to_s
88
- raise HTTPException.new(304)
83
+ not_modified!
89
84
  end
90
85
  response.headers['Last-Modified'] = last_modified
91
86
  end
@@ -93,7 +88,7 @@ module Restfulness
93
88
  def check_etag
94
89
  tag = request.headers[:if_none_match]
95
90
  if tag && tag == etag.to_s
96
- raise HTTPException.new(304)
91
+ not_modified!
97
92
  end
98
93
  response.headers['ETag'] = etag
99
94
  end
@@ -0,0 +1,45 @@
1
+ module Restfulness
2
+ module Resources
3
+
4
+ # Special events that can be used in replies. The idea here is to cover
5
+ # the basic messages that most applications will deal with in their
6
+ # resources.
7
+ module Events
8
+
9
+ # Event definitions go here. We only support a limited subset
10
+ # so that we don't end up with loads of methods that are not used.
11
+ # If you'd like to see another, please send us a pull request!
12
+ SUPPORTED_EVENTS = [
13
+ # 300 Events
14
+ [304, :not_modified],
15
+
16
+ # 400 Events
17
+ [400, :bad_request],
18
+ [401, :unauthorized],
19
+ [402, :payment_required],
20
+ [403, :forbidden],
21
+ [404, :resource_not_found],
22
+ [405, :method_not_allowed],
23
+ [408, :request_timeout],
24
+ [409, :conflict],
25
+ [410, :gone],
26
+ [422, :unprocessable_entity]
27
+ ]
28
+
29
+ # Main error event handler
30
+ def error!(code, payload = "", opts = {})
31
+ raise HTTPException.new(code, payload, opts)
32
+ end
33
+
34
+ SUPPORTED_EVENTS.each do |row|
35
+ define_method("#{row[1]}!") do |*args|
36
+ payload = args.shift || ""
37
+ opts = args.shift || {}
38
+ error!(row[0], payload, opts)
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -7,14 +7,11 @@ module Restfulness
7
7
  attr_reader :request
8
8
 
9
9
  # Outgoing data
10
- attr_reader :code, :headers, :payload
11
-
10
+ attr_reader :status, :headers, :payload
12
11
 
13
12
  def initialize(request)
14
13
  @request = request
15
-
16
- # Default headers
17
- @headers = {'Content-Type' => 'application/json; charset=utf-8'}
14
+ @headers = {}
18
15
  end
19
16
 
20
17
  def run
@@ -31,15 +28,15 @@ module Restfulness
31
28
  # Perform the actual work
32
29
  result = resource.call
33
30
 
34
- @code ||= (result ? 200 : 204)
35
- @payload = MultiJson.encode(result)
31
+ update_status_and_payload(result.nil? ? 204 : 200, result)
36
32
  else
37
- logger.error("No route found")
38
- # This is not something we can deal with, pass it on
39
- @code = 404
40
- @payload = ""
33
+ update_status_and_payload(404)
41
34
  end
42
- update_content_length
35
+
36
+ rescue HTTPException => e # Deal with HTTP exceptions
37
+ logger.error(e.message)
38
+ headers.update(e.headers)
39
+ update_status_and_payload(e.status, e.payload)
43
40
  end
44
41
 
45
42
  def logger
@@ -47,9 +44,34 @@ module Restfulness
47
44
  end
48
45
 
49
46
  protected
47
+
48
+ def update_status_and_payload(status, payload = "")
49
+ self.status = status
50
+ self.payload = payload
51
+ end
52
+
53
+ def status=(code)
54
+ @status = code
55
+ end
56
+
57
+ def payload=(body)
58
+ if body.nil? || body.is_a?(String)
59
+ @payload = body.to_s
60
+ update_content_headers(:text)
61
+ else
62
+ @payload = MultiJson.encode(body)
63
+ update_content_headers(:json)
64
+ end
65
+ end
50
66
 
51
- def update_content_length
52
- @headers['Content-Length'] = @payload.bytesize.to_s
67
+ def update_content_headers(type = :json)
68
+ case type
69
+ when :json
70
+ headers['Content-Type'] = 'application/json; charset=utf-8'
71
+ else # Assume text
72
+ headers['Content-Type'] = 'text/plain; charset=utf-8'
73
+ end
74
+ headers['Content-Length'] = payload.to_s.bytesize.to_s
53
75
  end
54
76
 
55
77
  end
@@ -1,3 +1,3 @@
1
1
  module Restfulness
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -5,13 +5,13 @@ describe Restfulness::HTTPException do
5
5
  describe "#initialize" do
6
6
  it "should assign variables" do
7
7
  obj = Restfulness::HTTPException.new(200, "payload", :message => 'foo', :headers => {})
8
- obj.code.should eql(200)
8
+ obj.status.should eql(200)
9
9
  obj.payload.should eql("payload")
10
10
  obj.message.should eql('foo')
11
11
  obj.headers.should eql({})
12
12
  end
13
13
 
14
- it "should use status code for message if none provided" do
14
+ it "should use status status for message if none provided" do
15
15
  obj = Restfulness::HTTPException.new(200, "payload")
16
16
  obj.message.should eql('OK')
17
17
  end
@@ -224,22 +224,4 @@ describe Restfulness::Resource do
224
224
  end
225
225
  end
226
226
 
227
- describe "#error" do
228
-
229
- class Get418Resource < Restfulness::Resource
230
- def get
231
- error(418, {})
232
- end
233
- end
234
-
235
- it "should raise a new exception" do
236
- klass = Get418Resource
237
- obj = klass.new(request, response)
238
- expect {
239
- obj.get
240
- }.to raise_error(Restfulness::HTTPException, "I'm A Teapot")
241
- end
242
-
243
- end
244
-
245
227
  end
@@ -0,0 +1,68 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe Restfulness::Resources::Events do
5
+
6
+ let :app do
7
+ Class.new(Restfulness::Application) do
8
+ routes do
9
+ # empty
10
+ end
11
+ end
12
+ end
13
+ let :request do
14
+ Restfulness::Request.new(app)
15
+ end
16
+ let :response do
17
+ Restfulness::Response.new(request)
18
+ end
19
+
20
+
21
+ describe "#error" do
22
+
23
+ class Get418Resource < Restfulness::Resource
24
+ def get
25
+ error!(418, {})
26
+ end
27
+ end
28
+
29
+ it "should raise a new exception" do
30
+ klass = Get418Resource
31
+ obj = klass.new(request, response)
32
+ expect {
33
+ obj.get
34
+ }.to raise_error(Restfulness::HTTPException, "I'm A Teapot")
35
+ end
36
+ end
37
+
38
+ describe "generic bang error events" do
39
+
40
+ let :klass do
41
+ Class.new(Restfulness::Resource)
42
+ end
43
+
44
+ let :obj do
45
+ klass.new(request, response)
46
+ end
47
+
48
+ it "should support bad_request!" do
49
+ expect {
50
+ obj.instance_eval do
51
+ bad_request!
52
+ end
53
+ }.to raise_error(Restfulness::HTTPException, "Bad Request")
54
+ end
55
+
56
+ it "should support bad_request! with paramters" do
57
+ obj.should_receive(:error!).with(400, {:pay => 'load'}, {})
58
+ obj.instance_eval do
59
+ bad_request!({:pay => 'load'}, {})
60
+ end
61
+ end
62
+
63
+
64
+ end
65
+
66
+
67
+
68
+ end
@@ -26,8 +26,9 @@ describe Restfulness::Response do
26
26
  describe "#initialize" do
27
27
  it "should assign request and headers" do
28
28
  obj.request.should eql(request)
29
- obj.headers.should eql({'Content-Type' => 'application/json; charset=utf-8'})
30
- obj.code.should be_nil
29
+ obj.headers.should eql({})
30
+ obj.status.should be_nil
31
+ obj.payload.should be_nil
31
32
  end
32
33
  end
33
34
 
@@ -36,8 +37,9 @@ describe Restfulness::Response do
36
37
  it "should not do anything" do
37
38
  request.stub(:route).and_return(nil)
38
39
  obj.run
39
- obj.code.should eql(404)
40
+ obj.status.should eql(404)
40
41
  obj.payload.should be_empty
42
+ obj.headers['Content-Type'].should match(/text\/plain/)
41
43
  obj.headers['Content-Length'].should eql(0.to_s)
42
44
  end
43
45
  end
@@ -54,12 +56,76 @@ describe Restfulness::Response do
54
56
  resource.should_receive(:call).and_return({:foo => 'bar'})
55
57
  route.stub(:build_resource).and_return(resource)
56
58
  obj.run
57
- obj.code.should eql(200)
59
+ obj.status.should eql(200)
58
60
  str = "{\"foo\":\"bar\"}"
59
61
  obj.payload.should eql(str)
62
+ obj.headers['Content-Type'].should match(/application\/json/)
60
63
  obj.headers['Content-Length'].should eql(str.bytesize.to_s)
61
- end
64
+ end
65
+
66
+ it "should call resource and set 204 result if no content" do
67
+ request.stub(:route).and_return(route)
68
+ request.action = :get
69
+ resource = double(:Resource)
70
+ resource.should_receive(:check_callbacks)
71
+ resource.should_receive(:call).and_return(nil)
72
+ route.stub(:build_resource).and_return(resource)
73
+ obj.run
74
+ obj.status.should eql(204)
75
+ obj.headers['Content-Type'].should match(/text\/plain/)
76
+ end
77
+
78
+ it "should set string content type if payload is a string" do
79
+ request.stub(:route).and_return(route)
80
+ request.action = :get
81
+ resource = double(:Resource)
82
+ resource.should_receive(:check_callbacks)
83
+ resource.should_receive(:call).and_return("This is a text message")
84
+ route.stub(:build_resource).and_return(resource)
85
+ obj.run
86
+ obj.status.should eql(200)
87
+ obj.headers['Content-Type'].should match(/text\/plain/)
88
+ end
62
89
  end
90
+
91
+ context "with exceptions" do
92
+ let :route do
93
+ app.router.routes.first
94
+ end
95
+
96
+ it "should update the status and payload" do
97
+ request.stub(:route).and_return(route)
98
+ request.action = :get
99
+ resource = double(:Resource)
100
+ txt = "This is a text error"
101
+ resource.stub(:check_callbacks) do
102
+ raise Restfulness::HTTPException.new(418, txt)
103
+ end
104
+ route.stub(:build_resource).and_return(resource)
105
+ obj.run
106
+ obj.status.should eql(418)
107
+ obj.headers['Content-Type'].should match(/text\/plain/)
108
+ obj.payload.should eql(txt)
109
+ end
110
+
111
+ it "should update the status and provide JSON payload" do
112
+ request.stub(:route).and_return(route)
113
+ request.action = :get
114
+ resource = double(:Resource)
115
+ err = {:error => "This is a text error"}
116
+ resource.stub(:check_callbacks) do
117
+ raise Restfulness::HTTPException.new(418, err)
118
+ end
119
+ route.stub(:build_resource).and_return(resource)
120
+ obj.run
121
+ obj.status.should eql(418)
122
+ obj.headers['Content-Type'].should match(/application\/json/)
123
+ obj.payload.should eql(err.to_json)
124
+ end
125
+
126
+
127
+ end
128
+
63
129
  end
64
130
 
65
131
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restfulness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Lown
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-16 00:00:00.000000000 Z
11
+ date: 2013-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -134,6 +134,7 @@ files:
134
134
  - lib/restfulness/path.rb
135
135
  - lib/restfulness/request.rb
136
136
  - lib/restfulness/resource.rb
137
+ - lib/restfulness/resources/events.rb
137
138
  - lib/restfulness/response.rb
138
139
  - lib/restfulness/route.rb
139
140
  - lib/restfulness/router.rb
@@ -148,6 +149,7 @@ files:
148
149
  - spec/unit/path_spec.rb
149
150
  - spec/unit/request_spec.rb
150
151
  - spec/unit/resource_spec.rb
152
+ - spec/unit/resources/events_spec.rb
151
153
  - spec/unit/response_spec.rb
152
154
  - spec/unit/route_spec.rb
153
155
  - spec/unit/router_spec.rb
@@ -184,6 +186,7 @@ test_files:
184
186
  - spec/unit/path_spec.rb
185
187
  - spec/unit/request_spec.rb
186
188
  - spec/unit/resource_spec.rb
189
+ - spec/unit/resources/events_spec.rb
187
190
  - spec/unit/response_spec.rb
188
191
  - spec/unit/route_spec.rb
189
192
  - spec/unit/router_spec.rb