wor-simple_crud 0.2.1
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 +7 -0
- data/.github/workflows/ci.yml +52 -0
- data/.gitignore +338 -0
- data/.overcommit.yml +15 -0
- data/.rubocop.yml +16 -0
- data/Appraisals +40 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +42 -0
- data/LICENSE.md +22 -0
- data/README.md +286 -0
- data/Rakefile +6 -0
- data/lib/simple_crud/authorization/action_policy_adapter.rb +22 -0
- data/lib/simple_crud/authorization/adapter.rb +20 -0
- data/lib/simple_crud/authorization/can_can_can_adapter.rb +22 -0
- data/lib/simple_crud/authorization/pundit_adapter.rb +21 -0
- data/lib/simple_crud/config.rb +24 -0
- data/lib/simple_crud/pagination/adapter.rb +14 -0
- data/lib/simple_crud/pagination/kaminari_adapter.rb +19 -0
- data/lib/simple_crud/pagination/pagy_adapter.rb +22 -0
- data/lib/simple_crud/pagination/will_paginate_adapter.rb +22 -0
- data/lib/simple_crud/pagination/wor_paginate_adapter.rb +17 -0
- data/lib/simple_crud/rspec.rb +11 -0
- data/lib/simple_crud/simple_crud_controller.rb +125 -0
- data/lib/simple_crud/version.rb +5 -0
- data/lib/simple_crud.rb +12 -0
- data/lib/spec/matchers/have_been_serialized_with.rb +30 -0
- data/lib/spec/response_helper.rb +10 -0
- data/lib/spec/shared_contexts/authenticate_user.rb +11 -0
- data/lib/spec/shared_examples/helpers.rb +50 -0
- data/lib/spec/shared_examples/simple_crud_for_create.rb +49 -0
- data/lib/spec/shared_examples/simple_crud_for_destroy.rb +68 -0
- data/lib/spec/shared_examples/simple_crud_for_index.rb +56 -0
- data/lib/spec/shared_examples/simple_crud_for_show.rb +51 -0
- data/lib/spec/shared_examples/simple_crud_for_update.rb +61 -0
- data/lib/spec/shared_examples/unauthorized_when_not_logged_in.rb +10 -0
- data/pull_request_template.md +3 -0
- data/spec/dummy/Rakefile +8 -0
- data/spec/dummy/app/assets/config/manifest.js +6 -0
- data/spec/dummy/app/controllers/application_controller.rb +38 -0
- data/spec/dummy/app/controllers/dummy_models_controller.rb +23 -0
- data/spec/dummy/app/controllers/without_pagination/dummy_models_controller.rb +15 -0
- data/spec/dummy/app/models/application_record.rb +5 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/dummy_model.rb +7 -0
- data/spec/dummy/app/models/dummy_model_policy.rb +34 -0
- data/spec/dummy/app/models/user.rb +11 -0
- data/spec/dummy/app/serializers/dummy_model_serializer.rb +5 -0
- data/spec/dummy/bin/bundle +5 -0
- data/spec/dummy/bin/rails +6 -0
- data/spec/dummy/bin/rake +6 -0
- data/spec/dummy/bin/setup +35 -0
- data/spec/dummy/bin/update +30 -0
- data/spec/dummy/config/application.rb +17 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +7 -0
- data/spec/dummy/config/environments/development.rb +46 -0
- data/spec/dummy/config/environments/test.rb +47 -0
- data/spec/dummy/config/initializers/devise.rb +303 -0
- data/spec/dummy/config/locales/devise.en.yml +65 -0
- data/spec/dummy/config/puma.rb +49 -0
- data/spec/dummy/config/routes.rb +10 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config/spring.rb +8 -0
- data/spec/dummy/config.ru +7 -0
- data/spec/dummy/db/migrate/20170626184159_create_dummy_models.rb +10 -0
- data/spec/dummy/db/migrate/20200110191019_devise_create_users.rb +43 -0
- data/spec/dummy/db/migrate/20200120165657_add_user_id_to_dummy_models.rb +7 -0
- data/spec/dummy/db/schema.rb +36 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/spec/factories/dummy_models.rb +9 -0
- data/spec/dummy/spec/factories/users.rb +8 -0
- data/spec/dummy_controller_spec.rb +19 -0
- data/spec/dummy_model_policy_spec.rb +29 -0
- data/spec/dummy_model_serializer_spec.rb +36 -0
- data/spec/simple_crud/authorization/action_policy_adapter_spec.rb +58 -0
- data/spec/simple_crud/authorization/can_can_can_adapter_spec.rb +53 -0
- data/spec/simple_crud/pagination/adapters_spec.rb +48 -0
- data/spec/simple_crud_configuration_spec.rb +61 -0
- data/spec/simple_crud_controller_spec.rb +41 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/spy.rb +41 -0
- data/spec/without_pagination/dummy_models_controller_spec.rb +6 -0
- data/wor-simple_crud.gemspec +23 -0
- metadata +145 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec::Matchers.define :have_been_serialized_with do |serializer|
|
|
4
|
+
# TODO: Add support for optional relations `has_many :zarasa, if: zarasa2`
|
|
5
|
+
# TODO: Support multilevel serialization
|
|
6
|
+
match do |json_response|
|
|
7
|
+
[json_response].flatten.all? do |json_response_item|
|
|
8
|
+
all_attributes_included?(serializer._attributes, json_response_item) &&
|
|
9
|
+
all_attributes_included?(serializer._reflections.keys, json_response_item)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
failure_message do |json_response|
|
|
14
|
+
"expected attributes of #{serializer} serializer to be included in #{json_response}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
failure_message_when_negated do |json_response|
|
|
18
|
+
"expected attributes of #{serializer} serializer not to be included in #{json_response}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
description do
|
|
22
|
+
"checks to see if all the serializer's attributes are in the JSON response"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def all_attributes_included?(attributes, json_response)
|
|
26
|
+
attributes.all? do |attribute|
|
|
27
|
+
json_response.key?(attribute.to_s) || json_response.key?(attribute.to_sym)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_context 'with authenticated user' do
|
|
4
|
+
let(:current_user) { create(:user) }
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
|
|
8
|
+
auth_headers = Devise::JWT::TestHelpers.auth_headers(headers, current_user)
|
|
9
|
+
request.headers.merge!(auth_headers)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
def get_option(method, option)
|
|
4
|
+
described_class.instance_variable_get(:@simple_crud_metadata)[method][option]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
%i[paginate authorize authenticate serializer].each do |option|
|
|
8
|
+
define_method("check_#{option}") do |method|
|
|
9
|
+
get_option(method, option)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def model_class
|
|
14
|
+
described_class.to_s.split('::')
|
|
15
|
+
.last.sub('Controller', '').singularize.underscore
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def model_serializer
|
|
19
|
+
defined?(serializer) ? serializer : "#{model.class}_serializer".classify.constantize
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def model
|
|
23
|
+
@model ||= create(model_class, **model_attributes)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def model_attributes
|
|
27
|
+
respond_to?(:current_user) ? { user: current_user } : {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def model_class_object
|
|
31
|
+
model_class.classify.constantize
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def policy_class_object
|
|
35
|
+
"#{model_class_object}Policy".classify.constantize
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def make_policies_fail(method)
|
|
39
|
+
allow(policy_class_object).to receive(:new)
|
|
40
|
+
.and_return(instance_double(policy_class_object, "#{method}?" => false))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def make_policies_succeed(method)
|
|
44
|
+
allow(policy_class_object).to receive(:new)
|
|
45
|
+
.and_return(instance_double(policy_class_object, "#{method}?" => true))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def model_params
|
|
49
|
+
@model_params ||= attributes_for(model_class)
|
|
50
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'helpers'
|
|
4
|
+
|
|
5
|
+
shared_examples 'simple crud for create' do
|
|
6
|
+
describe 'POST #create' do
|
|
7
|
+
context 'without authenticated user' do
|
|
8
|
+
subject!(:req) { post :create, params: attributes_for(model_class) }
|
|
9
|
+
|
|
10
|
+
include_examples 'unauthorized when not logged in' if check_authenticate(:create)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
if check_authorize(:create)
|
|
14
|
+
context 'when not authorized' do
|
|
15
|
+
include_context 'with authenticated user' if check_authenticate(:create)
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
make_policies_fail(:create)
|
|
19
|
+
post :create, params: model_params
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'fails with forbidden' do
|
|
23
|
+
expect(response).to have_http_status(:forbidden)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'when successfully creating an article' do
|
|
29
|
+
include_context 'with authenticated user' if check_authenticate(:create)
|
|
30
|
+
let(:create_params) { model_params.merge(user_id: current_user.id) }
|
|
31
|
+
|
|
32
|
+
before do
|
|
33
|
+
post :create, params: create_params
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'response with 200 status code' do
|
|
37
|
+
expect(response).to have_http_status(:created)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'creates an article' do
|
|
41
|
+
expect(model_class_object.count).to be 1
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'creates an article with valid attributes' do
|
|
45
|
+
expect(model_class_object.last).to have_attributes(create_params)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
shared_examples 'simple crud for destroy' do
|
|
4
|
+
describe 'DELETE #destroy' do
|
|
5
|
+
context 'without authenticated user' do
|
|
6
|
+
subject!(:req) { delete :destroy, params: { id: 1 } }
|
|
7
|
+
|
|
8
|
+
include_examples 'unauthorized when not logged in' if check_authenticate(:destroy)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
if check_authorize(:destroy)
|
|
12
|
+
context 'when not authorized' do
|
|
13
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
make_policies_fail(:destroy)
|
|
17
|
+
delete :destroy, params: { id: model.id }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'fails with forbidden' do
|
|
21
|
+
expect(response).to have_http_status(:forbidden)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when ID is valid' do
|
|
27
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
model
|
|
31
|
+
delete :destroy, params: { id: model.id }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'response with 200 status code' do
|
|
35
|
+
expect(response).to have_http_status(:ok)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when ID is invalid' do
|
|
40
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
41
|
+
|
|
42
|
+
before do
|
|
43
|
+
model
|
|
44
|
+
delete :destroy, params: { id: model.id + 13 }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'responds with not found status' do
|
|
48
|
+
expect(response).to have_http_status(:not_found)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if check_authorize(:destroy)
|
|
53
|
+
context 'when ID is valid but user isn\'t authorized' do
|
|
54
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
55
|
+
|
|
56
|
+
before do
|
|
57
|
+
model
|
|
58
|
+
make_policies_fail(:destroy)
|
|
59
|
+
delete :destroy, params: { id: model.id }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'response with 200 status code' do
|
|
63
|
+
expect(response).to have_http_status(:forbidden)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
shared_examples 'simple crud for index' do
|
|
4
|
+
describe 'GET #index' do
|
|
5
|
+
let(:created_models) { create_list(model_class, 10) }
|
|
6
|
+
|
|
7
|
+
before { created_models }
|
|
8
|
+
|
|
9
|
+
context 'without authenticated user' do
|
|
10
|
+
subject!(:req) { get :index }
|
|
11
|
+
|
|
12
|
+
include_examples 'unauthorized when not logged in' if check_authenticate(:index)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
if check_authorize(:index)
|
|
16
|
+
context 'when not authorized' do
|
|
17
|
+
include_context 'with authenticated user' if check_authenticate(:index)
|
|
18
|
+
|
|
19
|
+
before do
|
|
20
|
+
make_policies_fail(:index)
|
|
21
|
+
get :index
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'fails with forbidden' do
|
|
25
|
+
expect(response).to have_http_status(:forbidden)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'with authenticated user' do
|
|
31
|
+
include_context 'with authenticated user' if check_authenticate(:index)
|
|
32
|
+
before do
|
|
33
|
+
make_policies_succeed(:index)
|
|
34
|
+
get :index
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if check_paginate(:index)
|
|
38
|
+
it 'renders paginated models correctly serialized' do
|
|
39
|
+
expect(response_body['page']).to have_been_serialized_with(model_serializer)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'renders the correct paginated models' do
|
|
43
|
+
expect(response_body['page'].map { |a| a['id'] }).to eq(model_class_object.all.map(&:id))
|
|
44
|
+
end
|
|
45
|
+
else
|
|
46
|
+
it 'renders unpaginated models correctly serialized' do
|
|
47
|
+
expect(response_body).to have_been_serialized_with(model_serializer)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'renders the correct unpaginated models' do
|
|
51
|
+
expect(response_body.map { |a| a['id'] }).to eq(model_class_object.all.map(&:id))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
shared_examples 'simple crud for show' do
|
|
4
|
+
describe 'GET #show' do
|
|
5
|
+
subject(:show_request) { get :show, params: show_params }
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
model
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context 'without authenticated user' do
|
|
12
|
+
subject!(:req) { get :show, params: { id: model.id } }
|
|
13
|
+
|
|
14
|
+
include_examples 'unauthorized when not logged in'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'when the model exists' do
|
|
18
|
+
include_context 'with authenticated user'
|
|
19
|
+
let(:show_params) { { id: model.id } }
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
show_request
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'responds with ok status' do
|
|
26
|
+
expect(response).to have_http_status(:ok)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'returns the asked model' do
|
|
30
|
+
expect(response_body['id']).to eq(model.id)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'have been serializer with model Serializer' do
|
|
34
|
+
expect(response_body).to have_been_serialized_with(model_serializer)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe 'when the model does not exist' do
|
|
39
|
+
include_context 'with authenticated user'
|
|
40
|
+
let(:show_params) { { id: -1 } }
|
|
41
|
+
|
|
42
|
+
before do
|
|
43
|
+
show_request
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'responds with not found status' do
|
|
47
|
+
expect(response).to have_http_status(:not_found)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
shared_examples 'simple crud for update' do
|
|
4
|
+
describe 'PUT #update' do
|
|
5
|
+
context 'without authenticated user' do
|
|
6
|
+
subject!(:req) { put :update, params: attributes_for(model_class).merge(id: model.id) }
|
|
7
|
+
|
|
8
|
+
include_examples 'unauthorized when not logged in'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
if check_authorize(:update)
|
|
12
|
+
context 'when not authorized' do
|
|
13
|
+
include_context 'with authenticated user' if check_authenticate(:update)
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
make_policies_fail(:update)
|
|
17
|
+
put :update, params: model_params.merge(id: model.id)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'fails with forbidden' do
|
|
21
|
+
expect(response).to have_http_status(:forbidden)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when successfully updating an model' do
|
|
27
|
+
include_context 'with authenticated user'
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
model
|
|
31
|
+
put :update, params: model_params.merge(id: model.id)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'response with 200 status code' do
|
|
35
|
+
expect(response).to have_http_status(:ok)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'updates an model' do
|
|
39
|
+
expect(model_class_object.count).to be 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'updates an model with valid attributes' do
|
|
43
|
+
expect(model_class.classify.constantize.last).to have_attributes(model_params)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context 'when updating a model that doesn\'t exist' do
|
|
48
|
+
include_context 'with authenticated user'
|
|
49
|
+
|
|
50
|
+
before { put :update, params: { id: 1 } }
|
|
51
|
+
|
|
52
|
+
it 'response with 422 status code' do
|
|
53
|
+
expect(response).to have_http_status(:not_found)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'doesn\'t create an model' do
|
|
57
|
+
expect(model_class_object.count).to be 0
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/spec/dummy/Rakefile
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
|
4
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
5
|
+
|
|
6
|
+
require_relative 'config/application'
|
|
7
|
+
|
|
8
|
+
Rails.application.load_tasks
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pagy'
|
|
4
|
+
|
|
5
|
+
class ApplicationController < ActionController::Base
|
|
6
|
+
# :unprocessable_entity was renamed :unprocessable_content in Rack 3.1.
|
|
7
|
+
# Older Rack (bundled with Rails 6.1/7.0) doesn't recognize the new name.
|
|
8
|
+
UNPROCESSABLE_STATUS = if Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(:unprocessable_content)
|
|
9
|
+
:unprocessable_content
|
|
10
|
+
else
|
|
11
|
+
:unprocessable_entity
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protect_from_forgery with: :exception
|
|
15
|
+
include Wor::Paginate
|
|
16
|
+
include Pagy::Method
|
|
17
|
+
include ActionController::MimeResponds
|
|
18
|
+
respond_to :json
|
|
19
|
+
# i18n configuration. See: http://guides.rubyonrails.org/i18n.html
|
|
20
|
+
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
|
21
|
+
rescue_from ActiveRecord::StatementInvalid, with: :unprocessable
|
|
22
|
+
rescue_from ActiveRecord::RecordInvalid, with: :unprocessable
|
|
23
|
+
rescue_from ActionController::ParameterMissing, with: :unprocessable
|
|
24
|
+
rescue_from Pundit::NotAuthorizedError, with: :forbidden
|
|
25
|
+
# TODO: find a less general way to catch wrong enum values
|
|
26
|
+
rescue_from ArgumentError, with: :unprocessable
|
|
27
|
+
def not_found(_exception)
|
|
28
|
+
head :not_found
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def unprocessable(exception)
|
|
32
|
+
render json: { errors: exception }, status: UNPROCESSABLE_STATUS
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def forbidden(exception)
|
|
36
|
+
render json: { errors: exception }, status: :forbidden
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class DummyModelsController < ApplicationController
|
|
4
|
+
include Wor::Paginate
|
|
5
|
+
|
|
6
|
+
include Pundit::Authorization
|
|
7
|
+
extend SimpleCrudController
|
|
8
|
+
|
|
9
|
+
before_action :set_params
|
|
10
|
+
def set_params
|
|
11
|
+
SimpleCrudController.params = params
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def dummy_model_params
|
|
15
|
+
params.permit(:name, :something, :user_id)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
simple_crud_for :create
|
|
19
|
+
simple_crud_for :destroy
|
|
20
|
+
simple_crud_for :update
|
|
21
|
+
simple_crud_for :show
|
|
22
|
+
simple_crud_for :index
|
|
23
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WithoutPagination
|
|
4
|
+
class DummyModelsController < ApplicationController
|
|
5
|
+
include Pundit::Authorization
|
|
6
|
+
extend SimpleCrudController
|
|
7
|
+
|
|
8
|
+
before_action :set_params
|
|
9
|
+
def set_params
|
|
10
|
+
SimpleCrudController.params = params
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
simple_crud_for :index, paginate: false
|
|
14
|
+
end
|
|
15
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class DummyModelPolicy
|
|
4
|
+
attr_reader :user, :dummy_model
|
|
5
|
+
|
|
6
|
+
def initialize(user, dummy_model)
|
|
7
|
+
@user = user
|
|
8
|
+
@dummy_model = dummy_model
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def check_user
|
|
12
|
+
user == dummy_model.user
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def show?
|
|
16
|
+
check_user
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update?
|
|
20
|
+
check_user
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create?
|
|
24
|
+
check_user
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def destroy?
|
|
28
|
+
check_user
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def index?
|
|
32
|
+
check_user
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class User < ApplicationRecord
|
|
4
|
+
# Include default devise modules. Others available are:
|
|
5
|
+
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
|
6
|
+
devise :database_authenticatable, :registerable,
|
|
7
|
+
:recoverable, :rememberable, :validatable, :jwt_authenticatable,
|
|
8
|
+
jwt_revocation_strategy: Devise::JWT::RevocationStrategies::Null
|
|
9
|
+
|
|
10
|
+
has_many :dummy_models
|
|
11
|
+
end
|
data/spec/dummy/bin/rake
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
# path to your application root.
|
|
8
|
+
APP_ROOT = Pathname.new File.expand_path('..', __dir__)
|
|
9
|
+
|
|
10
|
+
def system!(*args)
|
|
11
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
FileUtils.chdir APP_ROOT do
|
|
15
|
+
# This script is a starting point to setup your application.
|
|
16
|
+
# Add necessary setup steps to this file.
|
|
17
|
+
|
|
18
|
+
puts '== Installing dependencies =='
|
|
19
|
+
system! 'gem install bundler --conservative'
|
|
20
|
+
system('bundle check') || system!('bundle install')
|
|
21
|
+
|
|
22
|
+
# puts "\n== Copying sample files =="
|
|
23
|
+
# unless File.exist?('config/database.yml')
|
|
24
|
+
# cp 'config/database.yml.sample', 'config/database.yml'
|
|
25
|
+
# end
|
|
26
|
+
|
|
27
|
+
puts "\n== Preparing database =="
|
|
28
|
+
system! 'bin/rails db:setup'
|
|
29
|
+
|
|
30
|
+
puts "\n== Removing old logs and tempfiles =="
|
|
31
|
+
system! 'bin/rails log:clear tmp:clear'
|
|
32
|
+
|
|
33
|
+
puts "\n== Restarting application server =="
|
|
34
|
+
system! 'bin/rails restart'
|
|
35
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
# path to your application root.
|
|
8
|
+
APP_ROOT = Pathname.new File.expand_path('..', __dir__)
|
|
9
|
+
|
|
10
|
+
def system!(*args)
|
|
11
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
FileUtils.chdir APP_ROOT do
|
|
15
|
+
# This script is a way to update your development environment automatically.
|
|
16
|
+
# Add necessary update steps to this file.
|
|
17
|
+
|
|
18
|
+
puts '== Installing dependencies =='
|
|
19
|
+
system! 'gem install bundler --conservative'
|
|
20
|
+
system('bundle check') || system!('bundle install')
|
|
21
|
+
|
|
22
|
+
puts "\n== Updating database =="
|
|
23
|
+
system! 'bin/rails db:migrate'
|
|
24
|
+
|
|
25
|
+
puts "\n== Removing old logs and tempfiles =="
|
|
26
|
+
system! 'bin/rails log:clear tmp:clear'
|
|
27
|
+
|
|
28
|
+
puts "\n== Restarting application server =="
|
|
29
|
+
system! 'bin/rails restart'
|
|
30
|
+
end
|