rapid_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +120 -0
  3. data/lib/rapid_api/action_controller/errors.rb +75 -0
  4. data/lib/rapid_api/action_controller/filterable_params.rb +29 -0
  5. data/lib/rapid_api/action_controller/macros.rb +28 -0
  6. data/lib/rapid_api/action_controller/permitted_params.rb +38 -0
  7. data/lib/rapid_api/action_controller/rest_actions.rb +158 -0
  8. data/lib/rapid_api/action_controller/scope.rb +44 -0
  9. data/lib/rapid_api/action_controller.rb +11 -0
  10. data/lib/rapid_api/auth/concerns/authenticated_controller.rb +54 -0
  11. data/lib/rapid_api/auth/concerns/jwt_helpers.rb +33 -0
  12. data/lib/rapid_api/auth/concerns/sessions_controller.rb +49 -0
  13. data/lib/rapid_api/auth/concerns.rb +11 -0
  14. data/lib/rapid_api/auth/support/jwt.rb +28 -0
  15. data/lib/rapid_api/auth/support.rb +9 -0
  16. data/lib/rapid_api/auth.rb +8 -0
  17. data/lib/rapid_api/configuration.rb +11 -0
  18. data/lib/rapid_api/model_adapters/abstract.rb +33 -0
  19. data/lib/rapid_api/model_adapters/active_record_adapter.rb +49 -0
  20. data/lib/rapid_api/model_adapters/query_result.rb +22 -0
  21. data/lib/rapid_api/model_adapters.rb +9 -0
  22. data/lib/rapid_api/serializer_adapters/abstract.rb +22 -0
  23. data/lib/rapid_api/serializer_adapters/ams_adapter.rb +20 -0
  24. data/lib/rapid_api/serializer_adapters.rb +8 -0
  25. data/lib/rapid_api/version.rb +3 -0
  26. data/lib/rapid_api.rb +36 -0
  27. data/test/integration/ams_ar_test.rb +44 -0
  28. data/test/support/code_climate.rb +2 -0
  29. data/test/support/models.rb +24 -0
  30. data/test/support/schema.rb +14 -0
  31. data/test/support/serializers.rb +7 -0
  32. data/test/support/test_model_adapter.rb +23 -0
  33. data/test/support/test_module/test_model_adapter.rb +25 -0
  34. data/test/support/test_serializer_adapter.rb +10 -0
  35. data/test/test_helper.rb +28 -0
  36. data/test/unit/rapid_api/action_controller/errors_test.rb +53 -0
  37. data/test/unit/rapid_api/action_controller/filterable_params_test.rb +32 -0
  38. data/test/unit/rapid_api/action_controller/permitted_params_test.rb +30 -0
  39. data/test/unit/rapid_api/action_controller/rest_actions_test.rb +160 -0
  40. data/test/unit/rapid_api/action_controller/scope_test.rb +29 -0
  41. data/test/unit/rapid_api/auth/concerns/authenticated_controller_test.rb +56 -0
  42. data/test/unit/rapid_api/auth/concerns/sessions_controller_test.rb +55 -0
  43. data/test/unit/rapid_api/auth/support/jwt_test.rb +28 -0
  44. data/test/unit/rapid_api/model_adapters/abstract_test.rb +45 -0
  45. data/test/unit/rapid_api/model_adapters/active_record_adapter_test.rb +121 -0
  46. data/test/unit/rapid_api/serializer_adapters/abstract_test.rb +27 -0
  47. data/test/unit/rapid_api/serializer_adapters/ams_adapter_test.rb +31 -0
  48. data/test/unit/rapid_api/test_configuration.rb +17 -0
  49. metadata +197 -0
@@ -0,0 +1,9 @@
1
+ require 'rapid_api/auth/support/jwt'
2
+
3
+ module RapidApi
4
+ module Auth
5
+ module Support
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ require 'rapid_api/auth/concerns'
2
+ require 'rapid_api/auth/support'
3
+
4
+ module RapidApi
5
+ module Auth
6
+
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module RapidApi
2
+ class Configuration
3
+ include Singleton
4
+
5
+ attr_accessor :model_adapter,
6
+ :serializer_adapter,
7
+ :auth_model,
8
+ :response_codes
9
+
10
+ end
11
+ end
@@ -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,9 @@
1
+ require 'rapid_api/model_adapters/abstract'
2
+ require 'rapid_api/model_adapters/query_result'
3
+ require 'rapid_api/model_adapters/active_record_adapter'
4
+
5
+ module RapidApi
6
+ module ModelAdapters
7
+
8
+ end
9
+ 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
@@ -0,0 +1,8 @@
1
+ require 'rapid_api/serializer_adapters/abstract'
2
+ require 'rapid_api/serializer_adapters/ams_adapter'
3
+
4
+ module RapidApi
5
+ module SerializerAdapters
6
+
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module RapidApi
2
+ VERSION = "0.1.0"
3
+ 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,2 @@
1
+ # require "codeclimate-test-reporter"
2
+ # CodeClimate::TestReporter.start
@@ -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,7 @@
1
+ require 'active_model_serializers'
2
+
3
+ class BrickSerializer < ActiveModel::Serializer
4
+ attributes :color,
5
+ :weight,
6
+ :material
7
+ 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
@@ -0,0 +1,10 @@
1
+ class TestSerializerAdapter < RapidApi::SerializerAdapters::Abstract
2
+ def serialize(member)
3
+ return nil
4
+ end
5
+
6
+ def serializer_collection(collection)
7
+ return nil
8
+ end
9
+
10
+ end
@@ -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