repia 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/davidan1981/repia.svg?branch=master)](https://travis-ci.org/davidan1981/repia)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/davidan1981/repia/badge.svg?branch=master)](https://coveralls.io/github/davidan1981/repia?branch=master)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/davidan1981/repia/badges/gpa.svg)](https://codeclimate.com/github/davidan1981/repia)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/repia.svg)](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
|