restfulness 0.1.0 → 0.2.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.
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