repia 0.1.1 → 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 +4 -4
- data/LICENSE +21 -0
- data/README.md +71 -0
- data/Rakefile +1 -0
- data/lib/repia/base_controller.rb +33 -0
- data/lib/repia/{core.rb → base_helper.rb} +12 -53
- data/lib/repia/uuid_model.rb +28 -0
- data/lib/repia/version.rb +1 -1
- data/lib/repia.rb +3 -1
- data/test/dummy/app/models/unique_model.rb +1 -0
- data/test/dummy/config/application.rb +1 -1
- data/test/dummy/config/environments/test.rb +2 -2
- data/test/dummy/log/test.log +1464 -2408
- data/test/repia_base_controller_test.rb +97 -0
- data/test/repia_middlewares_test.rb +20 -0
- data/test/repia_test.rb +0 -66
- data/test/repia_unique_model_test.rb +11 -0
- metadata +33 -27
- data/test/dummy/app/controllers/dummies_controller.rb +0 -36
- data/test/dummy/log/development.log +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58b009fb035768295085359fa8691131240bc972
|
4
|
+
data.tar.gz: cca0b9c1a35e7c92a489fe24362cae9128a019a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ac3b531337a59b00877e1e80ef38cf046bb0131db0a053971b64f1dca261219872dfa72b74525424f3504fcac9c02e024978aad4082c78fcea595d9d6b676ae
|
7
|
+
data.tar.gz: e9a7c31828bdecbae836a3a53e9abba1c26ada136a7f046a53d21aa8fabbc2a92a4f55d14ce81dae5259a0843c5ac4e7ac7a4ccd0bf11fd30edf5ee4a4c4777b
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 David An
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# repia
|
2
|
+
|
3
|
+
[](https://travis-ci.org/davidan1981/repia)
|
4
|
+
[](https://coveralls.io/github/davidan1981/repia?branch=master)
|
5
|
+
[](https://codeclimate.com/github/davidan1981/repia)
|
6
|
+
[](https://badge.fury.io/rb/repia)
|
7
|
+
|
8
|
+
Rails Essential Plug-in for API (or repia) is a Rails plugin that serves as
|
9
|
+
a collection of features that are useful for RESTful API development.
|
10
|
+
|
11
|
+
## Install
|
12
|
+
|
13
|
+
Add `gem 'repia'` to your project `Gemfile`.
|
14
|
+
|
15
|
+
## How to Use Repia
|
16
|
+
|
17
|
+
Edit `application_controller.rb` as the following:
|
18
|
+
|
19
|
+
class ApplicationController < Repia::BaseController
|
20
|
+
end
|
21
|
+
|
22
|
+
This will allow all controllers in the project to inherit from
|
23
|
+
`Repia::BaseController`, which gracefully handles all _code_ errors using
|
24
|
+
pre-defined HTTP errors.
|
25
|
+
|
26
|
+
Next, update all models that need UUID as a primary identifier:
|
27
|
+
|
28
|
+
class Something < ActiveRecord::Base
|
29
|
+
include Repia::UUIDModel
|
30
|
+
end
|
31
|
+
|
32
|
+
This will trigger UUID generation before a record object is created. Note
|
33
|
+
that migration must look similar to this:
|
34
|
+
|
35
|
+
class CreateSomethings < ActiveRecord::Migration
|
36
|
+
def change
|
37
|
+
create_table :somethings, id: false do |t|
|
38
|
+
t.string :uuid, primary_key: true, null: false
|
39
|
+
t.string :name
|
40
|
+
t.timestamps null: false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
## Middleware
|
46
|
+
|
47
|
+
When developing a JSON API, it is annoying to see non-JSON error responses
|
48
|
+
from a middleware. There are two prominent cases: `405 Method Not Allowed`
|
49
|
+
and `404 Not Found`. The former occurs when the request method is invalid
|
50
|
+
and the latter happens when the route does not match any controller or
|
51
|
+
action. Since these are caught within middleware, `rescue_from` does not
|
52
|
+
really help. So repia provides two useful components for this.
|
53
|
+
|
54
|
+
### Method Not Allowed
|
55
|
+
|
56
|
+
This class is a middleware that can be inserted (preferrably after
|
57
|
+
`ActionDispatch::RequestId`) to catch 405 errors. Instead of using a view
|
58
|
+
template, it will return a simple JSON response with a status of 405.
|
59
|
+
|
60
|
+
### Routing Error
|
61
|
+
|
62
|
+
Routing errors can be caught using `BaseController#exceptions_app`. To
|
63
|
+
configure it, add this to `config/application.rb`:
|
64
|
+
|
65
|
+
config.exceptions_app = lambda {|env| ApplicationController.action(:exceptions_app).call(env)}
|
66
|
+
|
67
|
+
*NOTE*: To enable this feature in development and in test,
|
68
|
+
`config/environments/development.rb` and `config/environments/test.rb` must
|
69
|
+
have
|
70
|
+
|
71
|
+
config.consider_all_requests_local = false
|
data/Rakefile
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'repia/errors'
|
3
|
+
require 'repia/base_helper'
|
4
|
+
|
5
|
+
module Repia
|
6
|
+
|
7
|
+
##
|
8
|
+
# This controller is a base controller for RESTful API. Two primary
|
9
|
+
# features:
|
10
|
+
#
|
11
|
+
# - Error (exception) handling
|
12
|
+
# - Options request handling
|
13
|
+
#
|
14
|
+
class BaseController < ActionController::Base
|
15
|
+
include BaseHelper
|
16
|
+
|
17
|
+
# This is a catch-all.
|
18
|
+
rescue_from StandardError do |exception|
|
19
|
+
logger.error exception.message
|
20
|
+
render_error 500, "Unknown error occurred: #{exception.message}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# Catch all manually thrown HTTP errors (predefined by repia)
|
24
|
+
rescue_from Errors::HTTPError do |exception|
|
25
|
+
status_code = exception.class.const_get("STATUS_CODE")
|
26
|
+
message = exception.message || exception.class::MESSAGE
|
27
|
+
logger.error "#{status_code} - #{message}"
|
28
|
+
render_error status_code, message
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -1,41 +1,26 @@
|
|
1
|
-
require 'json'
|
2
1
|
require 'repia/errors'
|
3
2
|
|
4
3
|
module Repia
|
5
4
|
|
6
5
|
##
|
7
|
-
# This module
|
8
|
-
#
|
9
|
-
# primary key is called "uuid" and an UUID is generated right before
|
10
|
-
# save(). You may assign an UUID prior to save, in which case, no new UUID
|
11
|
-
# will be generated.
|
6
|
+
# This helper module includes methods that are essential for building a
|
7
|
+
# RESTful API.
|
12
8
|
#
|
13
|
-
module UUIDModel
|
14
|
-
|
15
|
-
##
|
16
|
-
# Triggered when this module is included.
|
17
|
-
#
|
18
|
-
def self.included(klass)
|
19
|
-
klass.primary_key = "uuid"
|
20
|
-
klass.before_create :generate_uuid
|
21
|
-
end
|
22
|
-
|
23
|
-
##
|
24
|
-
# Generates an UUID for the model object.
|
25
|
-
#
|
26
|
-
def generate_uuid()
|
27
|
-
self.uuid = UUIDTools::UUID.timestamp_create().to_s if self.uuid.nil?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
9
|
module BaseHelper
|
32
10
|
|
33
11
|
##
|
34
12
|
# Use this as an action triggered by exceptions_app to return a JSON
|
35
|
-
# response to any middleware level exceptions
|
13
|
+
# response to any middleware level exceptions.
|
14
|
+
#
|
15
|
+
# For example,
|
16
|
+
#
|
17
|
+
# config.exceptions_app = lambda { |env|
|
18
|
+
# ApplicationController.action(:exceptions_app).call(env)
|
19
|
+
# }
|
36
20
|
#
|
37
21
|
def exceptions_app
|
38
|
-
|
22
|
+
ex_wrapper = ActionDispatch::ExceptionWrapper.new(Rails.env, @exception)
|
23
|
+
status = ex_wrapper.status_code.to_i
|
39
24
|
error = Errors::STATUS_CODE_TO_ERROR[status]
|
40
25
|
if error
|
41
26
|
message = error::MESSAGE
|
@@ -76,6 +61,7 @@ module Repia
|
|
76
61
|
render json: {errors: msgs}, status: status
|
77
62
|
end
|
78
63
|
|
64
|
+
# undef :find_object if method_defined? :find_object
|
79
65
|
##
|
80
66
|
# Finds an object by model and UUID and throws an error (which will be
|
81
67
|
# caught and re-thrown as an HTTP error) if the object does not exist.
|
@@ -94,31 +80,4 @@ module Repia
|
|
94
80
|
end
|
95
81
|
|
96
82
|
end
|
97
|
-
|
98
|
-
##
|
99
|
-
# This controller is a base controller for RESTful API. Two primary
|
100
|
-
# features:
|
101
|
-
#
|
102
|
-
# - Error (exception) handling
|
103
|
-
# - Options request handling
|
104
|
-
#
|
105
|
-
class BaseController < ActionController::Base
|
106
|
-
include BaseHelper
|
107
|
-
|
108
|
-
# This is a catch-all.
|
109
|
-
rescue_from StandardError do |exception|
|
110
|
-
logger.error exception.message
|
111
|
-
render_error 500, "Unknown error occurred: #{exception.message}"
|
112
|
-
end
|
113
|
-
|
114
|
-
# Catch all manually thrown HTTP errors (predefined by repia)
|
115
|
-
rescue_from Errors::HTTPError do |exception|
|
116
|
-
status_code = exception.class.const_get("STATUS_CODE")
|
117
|
-
message = exception.message || exception.class::MESSAGE
|
118
|
-
logger.error "#{status_code} - #{message}"
|
119
|
-
render_error status_code, message
|
120
|
-
end
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
83
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Repia
|
3
|
+
|
4
|
+
##
|
5
|
+
# This module is a mixin that allows the model to use UUIDs instead of
|
6
|
+
# normal IDs. By including this module, the model class declares that the
|
7
|
+
# primary key is called "uuid" and an UUID is generated right before
|
8
|
+
# save(). You may assign an UUID prior to save, in which case, no new UUID
|
9
|
+
# will be generated.
|
10
|
+
#
|
11
|
+
module UUIDModel
|
12
|
+
|
13
|
+
##
|
14
|
+
# Triggered when this module is included.
|
15
|
+
#
|
16
|
+
def self.included(klass)
|
17
|
+
klass.primary_key = "uuid"
|
18
|
+
klass.before_create :generate_uuid
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Generates an UUID for the model object.
|
23
|
+
#
|
24
|
+
def generate_uuid()
|
25
|
+
self.uuid = UUIDTools::UUID.timestamp_create().to_s if self.uuid.nil?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/repia/version.rb
CHANGED
data/lib/repia.rb
CHANGED
@@ -20,7 +20,7 @@ module Dummy
|
|
20
20
|
# config.i18n.default_locale = :de
|
21
21
|
|
22
22
|
# Do not swallow errors in after_commit/after_rollback callbacks.
|
23
|
-
config.active_record.raise_in_transactional_callbacks = true
|
23
|
+
# config.active_record.raise_in_transactional_callbacks = true
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -13,8 +13,8 @@ Rails.application.configure do
|
|
13
13
|
config.eager_load = false
|
14
14
|
|
15
15
|
# Configure static file server for tests with Cache-Control for performance.
|
16
|
-
config.
|
17
|
-
config.
|
16
|
+
config.public_file_server.enabled = true
|
17
|
+
config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
|
18
18
|
|
19
19
|
# Show full error reports and disable caching.
|
20
20
|
config.consider_all_requests_local = true
|