rapid_api 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +120 -0
- data/lib/rapid_api/action_controller/errors.rb +75 -0
- data/lib/rapid_api/action_controller/filterable_params.rb +29 -0
- data/lib/rapid_api/action_controller/macros.rb +28 -0
- data/lib/rapid_api/action_controller/permitted_params.rb +38 -0
- data/lib/rapid_api/action_controller/rest_actions.rb +158 -0
- data/lib/rapid_api/action_controller/scope.rb +44 -0
- data/lib/rapid_api/action_controller.rb +11 -0
- data/lib/rapid_api/auth/concerns/authenticated_controller.rb +54 -0
- data/lib/rapid_api/auth/concerns/jwt_helpers.rb +33 -0
- data/lib/rapid_api/auth/concerns/sessions_controller.rb +49 -0
- data/lib/rapid_api/auth/concerns.rb +11 -0
- data/lib/rapid_api/auth/support/jwt.rb +28 -0
- data/lib/rapid_api/auth/support.rb +9 -0
- data/lib/rapid_api/auth.rb +8 -0
- data/lib/rapid_api/configuration.rb +11 -0
- data/lib/rapid_api/model_adapters/abstract.rb +33 -0
- data/lib/rapid_api/model_adapters/active_record_adapter.rb +49 -0
- data/lib/rapid_api/model_adapters/query_result.rb +22 -0
- data/lib/rapid_api/model_adapters.rb +9 -0
- data/lib/rapid_api/serializer_adapters/abstract.rb +22 -0
- data/lib/rapid_api/serializer_adapters/ams_adapter.rb +20 -0
- data/lib/rapid_api/serializer_adapters.rb +8 -0
- data/lib/rapid_api/version.rb +3 -0
- data/lib/rapid_api.rb +36 -0
- data/test/integration/ams_ar_test.rb +44 -0
- data/test/support/code_climate.rb +2 -0
- data/test/support/models.rb +24 -0
- data/test/support/schema.rb +14 -0
- data/test/support/serializers.rb +7 -0
- data/test/support/test_model_adapter.rb +23 -0
- data/test/support/test_module/test_model_adapter.rb +25 -0
- data/test/support/test_serializer_adapter.rb +10 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/rapid_api/action_controller/errors_test.rb +53 -0
- data/test/unit/rapid_api/action_controller/filterable_params_test.rb +32 -0
- data/test/unit/rapid_api/action_controller/permitted_params_test.rb +30 -0
- data/test/unit/rapid_api/action_controller/rest_actions_test.rb +160 -0
- data/test/unit/rapid_api/action_controller/scope_test.rb +29 -0
- data/test/unit/rapid_api/auth/concerns/authenticated_controller_test.rb +56 -0
- data/test/unit/rapid_api/auth/concerns/sessions_controller_test.rb +55 -0
- data/test/unit/rapid_api/auth/support/jwt_test.rb +28 -0
- data/test/unit/rapid_api/model_adapters/abstract_test.rb +45 -0
- data/test/unit/rapid_api/model_adapters/active_record_adapter_test.rb +121 -0
- data/test/unit/rapid_api/serializer_adapters/abstract_test.rb +27 -0
- data/test/unit/rapid_api/serializer_adapters/ams_adapter_test.rb +31 -0
- data/test/unit/rapid_api/test_configuration.rb +17 -0
- metadata +197 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module RapidApi
|
2
|
+
module ModelAdapters
|
3
|
+
class Abstract
|
4
|
+
|
5
|
+
attr_accessor :klass
|
6
|
+
|
7
|
+
def initialize(klass)
|
8
|
+
@klass = klass
|
9
|
+
end
|
10
|
+
|
11
|
+
def find(_id, _scope=nil)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_all(_params=nil, _scope=nil)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def create(_params, _scope=nil)
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def update(_id, _params, _scope=nil)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy(_id, _scope=nil)
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RapidApi
|
2
|
+
module ModelAdapters
|
3
|
+
class ActiveRecordAdapter < Abstract
|
4
|
+
|
5
|
+
def find(id, scope=nil)
|
6
|
+
member = _find_member_with_scope(id, scope)
|
7
|
+
QueryResult.new data: member
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_all(params=nil, scope=nil)
|
11
|
+
params ||= {}
|
12
|
+
scope ||= {}
|
13
|
+
scoped_params = params.merge scope
|
14
|
+
collection = klass.where(scoped_params)
|
15
|
+
QueryResult.new data: collection
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(params, scope=nil)
|
19
|
+
scope ||= {}
|
20
|
+
create_params = params.merge scope
|
21
|
+
member = klass.create create_params
|
22
|
+
_query_result_for_member member
|
23
|
+
end
|
24
|
+
|
25
|
+
def update(id, params, scope=nil)
|
26
|
+
member = _find_member_with_scope(id, scope)
|
27
|
+
member.update_attributes params
|
28
|
+
_query_result_for_member member
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy(id, scope=nil)
|
32
|
+
member = _find_member_with_scope(id, scope)
|
33
|
+
member.destroy
|
34
|
+
_query_result_for_member member
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def _query_result_for_member(member)
|
40
|
+
QueryResult.new data: member, errors: member.errors
|
41
|
+
end
|
42
|
+
|
43
|
+
def _find_member_with_scope(id, scope)
|
44
|
+
klass.where(scope).where(id: id).first
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RapidApi
|
2
|
+
module ModelAdapters
|
3
|
+
|
4
|
+
class QueryResult
|
5
|
+
attr_accessor :errors, :data
|
6
|
+
|
7
|
+
def initialize(data: nil, errors: nil)
|
8
|
+
@data = data
|
9
|
+
@errors = errors
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_errors?
|
13
|
+
errors.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
def found?
|
17
|
+
data.present?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RapidApi
|
2
|
+
module SerializerAdapters
|
3
|
+
class Abstract
|
4
|
+
|
5
|
+
attr_accessor :klass, :root_key
|
6
|
+
|
7
|
+
def initialize(klass, root_key)
|
8
|
+
@klass = klass
|
9
|
+
@root_key = root_key
|
10
|
+
end
|
11
|
+
|
12
|
+
def serialize(_member)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def serialize_collection(_collection)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RapidApi
|
2
|
+
module SerializerAdapters
|
3
|
+
class AmsAdapter < Abstract
|
4
|
+
|
5
|
+
def serialize(member)
|
6
|
+
serializer = klass.new(member)
|
7
|
+
serializer.to_json
|
8
|
+
end
|
9
|
+
|
10
|
+
def serialize_collection(collection)
|
11
|
+
array_serializer = ActiveModel::ArraySerializer.new collection, {
|
12
|
+
each_serializer: klass
|
13
|
+
}
|
14
|
+
array_serializer.root = root_key.pluralize
|
15
|
+
array_serializer.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/rapid_api.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rapid_api/version'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'rapid_api/model_adapters'
|
4
|
+
require 'rapid_api/serializer_adapters'
|
5
|
+
require 'rapid_api/action_controller'
|
6
|
+
require 'rapid_api/auth'
|
7
|
+
require 'rapid_api/configuration'
|
8
|
+
|
9
|
+
module RapidApi
|
10
|
+
|
11
|
+
Configuration.instance.tap do |c|
|
12
|
+
c.model_adapter = ModelAdapters::ActiveRecordAdapter
|
13
|
+
c.serializer_adapter = SerializerAdapters::AmsAdapter
|
14
|
+
c.response_codes = {
|
15
|
+
:ok => :ok,
|
16
|
+
:created => :created,
|
17
|
+
:not_found => :not_found,
|
18
|
+
:unprocessable_entity => :unprocessable_entity,
|
19
|
+
:unauthorized => :unauthorized,
|
20
|
+
:internal_server_error => :internal_server_error
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.config
|
25
|
+
Configuration.instance
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
if defined?(ActionController::Base)
|
31
|
+
ActionController::Base.send :include, RapidApi::ActionController::Macros
|
32
|
+
end
|
33
|
+
|
34
|
+
if defined?(ActionController::API)
|
35
|
+
ActionController::API.send :include, RapidApi::ActionController::Macros
|
36
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path '../../test_helper.rb', __FILE__
|
2
|
+
|
3
|
+
class AmsArTest < ActionController::TestCase
|
4
|
+
class AmsArIntegrationController < ActionController::Base
|
5
|
+
include RapidApi::ActionController::Errors
|
6
|
+
|
7
|
+
rapid_actions model: Brick, serializer: BrickSerializer
|
8
|
+
|
9
|
+
scope_by :user_id do |controller|
|
10
|
+
controller.params['user_id']
|
11
|
+
end
|
12
|
+
|
13
|
+
permit_params :color, :weight, :material
|
14
|
+
end
|
15
|
+
|
16
|
+
tests AmsArIntegrationController
|
17
|
+
|
18
|
+
def setup
|
19
|
+
super
|
20
|
+
DatabaseCleaner.start
|
21
|
+
Brick.delete_all
|
22
|
+
@user1 = User.create
|
23
|
+
@user2 = User.create
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown
|
27
|
+
DatabaseCleaner.clean
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_index
|
31
|
+
Brick.destroy_all
|
32
|
+
brick1 = @user1.bricks.create color: 'yellow', weight: 10, material: 'gold'
|
33
|
+
brick2 = @user1.bricks.create color: 'red', weight: 1, material: 'clay'
|
34
|
+
brick3 = @user2.bricks.create color: 'magenta', weight: 0, material: 'feathers'
|
35
|
+
get :index, { user_id: @user1.id }
|
36
|
+
assert_equal "{\"bricks\":[{\"color\":\"yellow\",\"weight\":\"10.0\",\"material\":\"gold\"},{\"color\":\"red\",\"weight\":\"1.0\",\"material\":\"clay\"}]}", response.body
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_show
|
40
|
+
brick = Brick.create color: 'red', weight: 1, material: 'clay'
|
41
|
+
get :show, {id: brick.id}
|
42
|
+
assert_equal "{\"brick\":{\"color\":\"red\",\"weight\":\"1.0\",\"material\":\"clay\"}}", response.body
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'database_cleaner'
|
3
|
+
|
4
|
+
ActiveRecord::Base.establish_connection adapter: :sqlite3,
|
5
|
+
database: 'memory'
|
6
|
+
|
7
|
+
DatabaseCleaner.strategy = :transaction
|
8
|
+
|
9
|
+
class Brick < ActiveRecord::Base
|
10
|
+
validates_uniqueness_of :color
|
11
|
+
before_destroy :prevent_destroy
|
12
|
+
belongs_to :user
|
13
|
+
|
14
|
+
def prevent_destroy
|
15
|
+
errors.add(:base, "Destroy prevented") if color == 'prevent_destroy'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class User < ActiveRecord::Base
|
20
|
+
has_many :bricks
|
21
|
+
def find_and_authenticate(params)
|
22
|
+
where(username: params[:username], password: params[:password]).first
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
connection.drop_table :bricks if connection.table_exists? :bricks
|
3
|
+
connection.drop_table :users if connection.table_exists? :users
|
4
|
+
create_table :bricks do |t|
|
5
|
+
t.string :color
|
6
|
+
t.decimal :weight
|
7
|
+
t.string :material
|
8
|
+
t.integer :user_id
|
9
|
+
end
|
10
|
+
create_table :users do |t|
|
11
|
+
t.string :username
|
12
|
+
t.string :password
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class TestModelAdapter < RapidApi::ModelAdapters::Abstract
|
2
|
+
|
3
|
+
def find(params, scope)
|
4
|
+
return nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_all(params, scope)
|
8
|
+
return nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(params, scope)
|
12
|
+
return nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def update(params, scope)
|
16
|
+
return nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def destroy(params, scope)
|
20
|
+
return nil
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TestModule
|
2
|
+
class TestModelAdapter < RapidApi::ModelAdapters::Abstract
|
3
|
+
|
4
|
+
def find(params)
|
5
|
+
return nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def find_all(params)
|
9
|
+
return nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(params)
|
13
|
+
return nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def update(params)
|
17
|
+
return nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def destroy(params)
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'pry'
|
3
|
+
require 'rails'
|
4
|
+
require 'action_controller'
|
5
|
+
require 'action_controller/test_case'
|
6
|
+
require 'rapid_api'
|
7
|
+
require 'minitest/autorun'
|
8
|
+
|
9
|
+
Dir['./test/support/**/*.rb'].each {|f| require f}
|
10
|
+
|
11
|
+
module TestHelper
|
12
|
+
Routes = ActionDispatch::Routing::RouteSet.new
|
13
|
+
Routes.draw do
|
14
|
+
get ':controller(/:action(/:id))'
|
15
|
+
get ':controller(/:action)'
|
16
|
+
end
|
17
|
+
|
18
|
+
ActionController::Base.send :include, Routes.url_helpers
|
19
|
+
end
|
20
|
+
|
21
|
+
ActionController::TestCase.class_eval do
|
22
|
+
def setup
|
23
|
+
@routes = TestHelper::Routes
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path '../../../../test_helper.rb', __FILE__
|
2
|
+
|
3
|
+
class ActionControllerErrorsTest < ActionController::TestCase
|
4
|
+
|
5
|
+
class TestErroneousController < ActionController::Base
|
6
|
+
include RapidApi::ActionController::Errors
|
7
|
+
|
8
|
+
def unauthenticated_action
|
9
|
+
not_authenticated!
|
10
|
+
end
|
11
|
+
|
12
|
+
def not_found_action
|
13
|
+
not_found!
|
14
|
+
end
|
15
|
+
|
16
|
+
def not_processable_action
|
17
|
+
brick = Brick.create
|
18
|
+
brick.errors.add(:base, 'Sample Error')
|
19
|
+
not_processable!(brick.errors)
|
20
|
+
end
|
21
|
+
|
22
|
+
def server_error_action
|
23
|
+
raise "server error message"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
tests TestErroneousController
|
29
|
+
|
30
|
+
def test_unauthenticated_error
|
31
|
+
get :unauthenticated_action
|
32
|
+
assert_response :unauthorized
|
33
|
+
assert_equal ['Not Authenticated'], JSON.parse(@controller.response.body)['errors']
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_server_error
|
37
|
+
get :server_error_action
|
38
|
+
assert_response :internal_server_error
|
39
|
+
assert_equal ['Server Error: server error message'], JSON.parse(@controller.response.body)['errors']
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_not_found_error
|
43
|
+
get :not_found_action
|
44
|
+
assert_response :not_found
|
45
|
+
assert_equal ['Not Found'], JSON.parse(@controller.response.body)['errors']
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_not_processable_error
|
49
|
+
get :not_processable_action
|
50
|
+
assert_response :unprocessable_entity
|
51
|
+
assert_equal ['Sample Error'], JSON.parse(@controller.response.body)['errors']['base']
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path '../../../../test_helper.rb', __FILE__
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
|
5
|
+
class FilterableParamsTest < ActionController::TestCase
|
6
|
+
|
7
|
+
class TestFilterableParamsController < ActionController::Base
|
8
|
+
include RapidApi::ActionController::FilterableParams
|
9
|
+
|
10
|
+
filterable_params :color
|
11
|
+
|
12
|
+
def filterable_bricks
|
13
|
+
render json: filterable_params, status: :ok
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
tests TestFilterableParamsController
|
18
|
+
|
19
|
+
def test_permitted_filterable_params
|
20
|
+
assert :color.in?(@controller.class.permitted_filterable_params), "Attribute not added to filterable params."
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_filterable_params
|
24
|
+
post :filterable_bricks, { color: 'blue', material: 'steel' }
|
25
|
+
body = JSON.parse(@controller.response.body)
|
26
|
+
expected = { 'color' => 'blue' }
|
27
|
+
assert_equal expected, body
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path '../../../../test_helper.rb', __FILE__
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
|
5
|
+
class PermittedParamsTest < ActionController::TestCase
|
6
|
+
|
7
|
+
class BricksController < ActionController::Base
|
8
|
+
include RapidApi::ActionController::PermittedParams
|
9
|
+
|
10
|
+
permit_params :color
|
11
|
+
|
12
|
+
def permissive_bricks
|
13
|
+
render json: _permitted_params_for(:brick).to_json, status: :ok
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
tests BricksController
|
18
|
+
|
19
|
+
def test_permits_params
|
20
|
+
assert :color.in?(@controller.permitted_params), "Attribute not added to permitted params."
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_permitted_params_for
|
24
|
+
post :permissive_bricks, {brick: {color: 'red', weight: 1}}
|
25
|
+
refute response.body.include?("\"weight\":\"1.0\""), ":attribute should not have been permitted."
|
26
|
+
assert response.body.include?("\"color\":\"red\""), ":attribute should have been permitted."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|