wor-simple_crud 0.6.0 → 0.8.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/CHANGELOG.md +26 -0
- data/README.md +116 -8
- data/lib/simple_crud/action_context.rb +16 -2
- data/lib/simple_crud/index_context.rb +21 -10
- data/lib/simple_crud/persistence_context.rb +16 -5
- data/lib/simple_crud/relation_source.rb +107 -0
- data/lib/simple_crud/rspec/config.rb +2 -0
- data/lib/simple_crud/rspec/helpers/controller_options.rb +1 -1
- data/lib/simple_crud/rspec/helpers/policies.rb +3 -3
- data/lib/simple_crud/rspec/helpers/requests.rb +4 -1
- data/lib/simple_crud/rspec/helpers/settings.rb +10 -1
- data/lib/simple_crud/rspec.rb +6 -0
- data/lib/simple_crud/serializer.rb +2 -7
- data/lib/simple_crud/simple_crud_controller.rb +28 -7
- data/lib/simple_crud/version.rb +1 -1
- data/lib/spec/matchers/render_or_redirect.rb +7 -0
- data/lib/spec/shared_examples/simple_crud_for_create.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_create_with_block.rb +2 -2
- data/lib/spec/shared_examples/simple_crud_for_create_with_build.rb +8 -2
- data/lib/spec/shared_examples/simple_crud_for_destroy.rb +11 -9
- data/lib/spec/shared_examples/simple_crud_for_destroy_with_block.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_edit.rb +16 -14
- data/lib/spec/shared_examples/simple_crud_for_edit_with_block.rb +22 -0
- data/lib/spec/shared_examples/simple_crud_for_edit_with_finder.rb +34 -0
- data/lib/spec/shared_examples/simple_crud_for_index_with_scope.rb +15 -12
- data/lib/spec/shared_examples/simple_crud_for_nested_resource.rb +21 -0
- data/lib/spec/shared_examples/simple_crud_for_new_with_block.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_new_with_build.rb +11 -5
- data/lib/spec/shared_examples/simple_crud_for_owned_resource.rb +45 -0
- data/lib/spec/shared_examples/simple_crud_for_show.rb +10 -8
- data/lib/spec/shared_examples/simple_crud_for_show_with_block.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_update.rb +14 -12
- data/lib/spec/shared_examples/simple_crud_for_update_with_block.rb +40 -0
- data/lib/spec/shared_examples/simple_crud_for_update_with_finder.rb +7 -4
- data/lib/spec/shared_examples/simple_crud_not_found_with_finder.rb +9 -7
- data/spec/block_create_redirect/dummy_models_controller_spec.rb +11 -0
- data/spec/block_edit/dummy_models_controller_spec.rb +7 -0
- data/spec/block_finder/dummy_models_controller_spec.rb +2 -0
- data/spec/block_policy_show/dummy_models_controller_spec.rb +7 -0
- data/spec/block_redirect/dummy_models_controller_spec.rb +1 -0
- data/spec/block_update/dummy_models_controller_spec.rb +11 -0
- data/spec/dummy/app/controllers/block_create_redirect/dummy_models_controller.rb +13 -0
- data/spec/dummy/app/controllers/block_edit/dummy_models_controller.rb +9 -0
- data/spec/dummy/app/controllers/block_policy_show/dummy_models_controller.rb +12 -0
- data/spec/dummy/app/controllers/block_update/dummy_models_controller.rb +9 -0
- data/spec/dummy/app/controllers/html_notice/dummy_models_controller.rb +11 -0
- data/spec/dummy/app/controllers/owned/dummy_models_controller.rb +21 -0
- data/spec/dummy/app/controllers/parented/dummy_models_controller.rb +24 -0
- data/spec/dummy/app/controllers/scoped_order/dummy_models_controller.rb +11 -0
- data/spec/dummy/app/controllers/scoped_symbol/dummy_models_controller.rb +11 -0
- data/spec/dummy/app/controllers/singular/dummy_models_controller.rb +12 -0
- data/spec/dummy/app/models/dummy_model.rb +4 -0
- data/spec/dummy/app/serializers/dummy_model_plain_serializer.rb +8 -0
- data/spec/dummy/app/views/block_edit/dummy_models/edit.html.erb +1 -0
- data/spec/dummy/app/views/block_policy_show/dummy_models/show.html.erb +1 -0
- data/spec/dummy/app/views/html_notice/dummy_models/edit.html.erb +1 -0
- data/spec/dummy/config/routes.rb +40 -0
- data/spec/finder/dummy_models_controller_spec.rb +6 -0
- data/spec/html_finder/dummy_models_controller_spec.rb +1 -0
- data/spec/html_notice/dummy_models_controller_spec.rb +38 -0
- data/spec/owned/dummy_models_controller_spec.rb +12 -0
- data/spec/parented/dummy_models_controller_spec.rb +39 -0
- data/spec/scoped_order/dummy_models_controller_spec.rb +10 -0
- data/spec/scoped_symbol/dummy_models_controller_spec.rb +7 -0
- data/spec/simple_crud/action_context_spec.rb +15 -0
- data/spec/simple_crud/index_context_spec.rb +49 -0
- data/spec/simple_crud/relation_source_spec.rb +125 -0
- data/spec/simple_crud/serializer_spec.rb +21 -0
- data/spec/simple_crud/show_context_spec.rb +5 -0
- data/spec/simple_crud_controller_spec.rb +15 -0
- data/spec/singular/dummy_models_controller_spec.rb +10 -0
- metadata +34 -2
|
@@ -4,6 +4,7 @@ require 'active_support/all'
|
|
|
4
4
|
require_relative 'config'
|
|
5
5
|
require_relative 'serializer'
|
|
6
6
|
require_relative 'cache_helpers'
|
|
7
|
+
require_relative 'relation_source'
|
|
7
8
|
require_relative 'action_context'
|
|
8
9
|
require_relative 'persistence_context'
|
|
9
10
|
require_relative 'show_context'
|
|
@@ -32,16 +33,26 @@ module SimpleCrudController
|
|
|
32
33
|
### serializer: use a particular serializer (both each_serializer and serializer)
|
|
33
34
|
### html: render the action's ERB template instead of JSON (index/show/new/edit/create/update/destroy)
|
|
34
35
|
### finder: custom record lookup (Proc/lambda or Symbol) for :show/:update/:destroy/:edit
|
|
35
|
-
### scope: custom index scope
|
|
36
|
+
### scope: custom index scope for :index, overriding policy_scope. A Proc/lambda run with the
|
|
37
|
+
### controller as self (arity 0 no args, arity 1 the user, else user and params), or a Symbol
|
|
38
|
+
### naming a model class method taking (current_user, params)
|
|
36
39
|
### build: custom record builder (Proc/lambda) for :new/:create, invoked with the controller as self
|
|
40
|
+
### owned_by: association on Config.user_method for the default finder/build/index-scope
|
|
41
|
+
### parent: nested-route parent for the same defaults; exclusive with owned_by:
|
|
42
|
+
### parent_association: parent association when it differs from the controller model's plural
|
|
43
|
+
### notice:/alert: flash on the html: create/update/destroy success redirect / failure re-render
|
|
37
44
|
### raise_on_invalid: use strict create!/update! semantics instead of returning 422
|
|
38
45
|
### A block given to simple_crud_for renders explicitly: it receives the records for :index,
|
|
39
46
|
### the record for :show/:new/:edit, or the record and a saved flag for :create/:update/:destroy
|
|
47
|
+
### An Array of actions declares several at once with the same options
|
|
40
48
|
def simple_crud_for(method, parameters = {}, &block)
|
|
49
|
+
return method.each { |name| simple_crud_for(name, parameters.dup, &block) } if method.is_a?(Array)
|
|
50
|
+
|
|
41
51
|
parameters[:block] = true if block
|
|
42
52
|
parameters = parameters_with_defaults(parameters)
|
|
43
53
|
klass = simple_crud_controller_model
|
|
44
54
|
check_valid_method(method)
|
|
55
|
+
check_relation_source(parameters)
|
|
45
56
|
check_policies(parameters)
|
|
46
57
|
check_serializer(parameters)
|
|
47
58
|
define_method(method, send("crud_lambda_for_#{method}", klass, parameters, &block))
|
|
@@ -62,18 +73,22 @@ module SimpleCrudController
|
|
|
62
73
|
end
|
|
63
74
|
|
|
64
75
|
def parameters_with_defaults(parameters)
|
|
65
|
-
defaults = {
|
|
66
|
-
authorize: true, paginate: true, authenticate: true, authenticate_headers: nil,
|
|
67
|
-
serializer: nil, serializer_options: nil, status: nil, after_persist: nil, html: false,
|
|
68
|
-
finder: nil, scope: nil, build: nil, raise_on_invalid: false
|
|
69
|
-
}
|
|
70
76
|
defaults.merge(simple_crud_inherited_defaults).each do |key, value|
|
|
71
77
|
parameters[key] = value unless parameters.key?(key)
|
|
72
78
|
end
|
|
73
|
-
parameters[:authenticate_headers]
|
|
79
|
+
parameters[:authenticate_headers] ||= parameters[:authenticate]
|
|
74
80
|
parameters
|
|
75
81
|
end
|
|
76
82
|
|
|
83
|
+
def defaults
|
|
84
|
+
{
|
|
85
|
+
authorize: true, paginate: true, authenticate: true, authenticate_headers: nil,
|
|
86
|
+
serializer: nil, serializer_options: nil, status: nil, after_persist: nil, html: false,
|
|
87
|
+
finder: nil, scope: nil, build: nil, owned_by: nil, parent: nil, parent_association: nil,
|
|
88
|
+
notice: nil, alert: nil, raise_on_invalid: false
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
|
|
77
92
|
def write_metadata(method, parameters)
|
|
78
93
|
@simple_crud_metadata ||= {}
|
|
79
94
|
@simple_crud_metadata[method] = parameters
|
|
@@ -87,6 +102,12 @@ module SimpleCrudController
|
|
|
87
102
|
raise ArgumentError, 'invalid method' unless %i[show index create update destroy new edit].include? method
|
|
88
103
|
end
|
|
89
104
|
|
|
105
|
+
def check_relation_source(parameters)
|
|
106
|
+
return unless parameters[:owned_by] && parameters[:parent]
|
|
107
|
+
|
|
108
|
+
raise ArgumentError, 'owned_by: and parent: are mutually exclusive, they both scope the same action'
|
|
109
|
+
end
|
|
110
|
+
|
|
90
111
|
def check_policies(parameters)
|
|
91
112
|
return if !parameters.key?(:authorize) || !parameters[:authorize]
|
|
92
113
|
|
data/lib/simple_crud/version.rb
CHANGED
|
@@ -53,7 +53,7 @@ RSpec.shared_examples 'simple crud for create' do
|
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
if invalid_case?(:create)
|
|
57
57
|
context 'when creating with invalid attributes' do
|
|
58
58
|
include_context 'with authenticated user' if check_authenticate(:create)
|
|
59
59
|
|
|
@@ -11,7 +11,7 @@ RSpec.shared_examples 'simple crud for create with block' do
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
it 'passes the saved record to the block' do
|
|
14
|
-
expect(response).to
|
|
14
|
+
expect(response).to render_or_redirect
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it 'creates the record' do
|
|
@@ -19,7 +19,7 @@ RSpec.shared_examples 'simple crud for create with block' do
|
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
if invalid_case?(:create)
|
|
23
23
|
context 'when creating with invalid attributes' do
|
|
24
24
|
include_context 'with authenticated user' if check_authenticate(:create)
|
|
25
25
|
|
|
@@ -8,8 +8,14 @@ RSpec.shared_examples 'simple crud for create with build' do
|
|
|
8
8
|
post :create, params: with_route_params(body_params(params_for(model_class))), format: format_param(:create)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
if owner_association
|
|
12
|
+
it 'creates the record owned by the current user' do
|
|
13
|
+
expect(model_class_object.last.public_send(owner_association)).to eq(current_user)
|
|
14
|
+
end
|
|
15
|
+
else
|
|
16
|
+
it 'creates the record through the hook' do
|
|
17
|
+
expect(model_class_object.count).to eq(1)
|
|
18
|
+
end
|
|
13
19
|
end
|
|
14
20
|
end
|
|
15
21
|
end
|
|
@@ -71,17 +71,19 @@ RSpec.shared_examples 'simple crud for destroy' do
|
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
unless singular
|
|
75
|
+
context 'when ID is invalid' do
|
|
76
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
before do
|
|
79
|
+
model
|
|
80
|
+
delete :destroy, params: with_route_params(record_param(:destroy, nil, not_found: true)),
|
|
81
|
+
format: format_param(:destroy)
|
|
82
|
+
end
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
it 'responds with not found status' do
|
|
85
|
+
expect(response).to have_http_status(:not_found)
|
|
86
|
+
end
|
|
85
87
|
end
|
|
86
88
|
end
|
|
87
89
|
|
|
@@ -41,38 +41,40 @@ RSpec.shared_examples 'simple crud for edit' do
|
|
|
41
41
|
|
|
42
42
|
before do
|
|
43
43
|
model
|
|
44
|
-
make_policies_succeed(:edit) if check_authorize(:edit)
|
|
44
|
+
make_policies_succeed(:edit, permissive: check_block(:edit)) if check_authorize(:edit)
|
|
45
45
|
edit_request
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
it 'responds with ok status' do
|
|
49
|
-
expect(response).to have_http_status(:ok)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
48
|
if check_block(:edit)
|
|
53
49
|
it 'renders the asked model through the block' do
|
|
54
|
-
expect(response).to
|
|
50
|
+
expect(response).to render_or_redirect
|
|
55
51
|
end
|
|
56
52
|
elsif check_html(:edit)
|
|
57
53
|
include_examples 'simple crud renders template', :edit
|
|
58
54
|
else
|
|
55
|
+
it 'responds with ok status' do
|
|
56
|
+
expect(response).to have_http_status(:ok)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
59
|
it 'returns the asked model' do
|
|
60
60
|
expect(response_body['id']).to eq(model.id)
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
unless singular
|
|
66
|
+
context 'when the model does not exist' do
|
|
67
|
+
include_context 'with authenticated user'
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
let(:edit_params) { record_param(:edit, nil, not_found: true) }
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
before do
|
|
72
|
+
edit_request
|
|
73
|
+
end
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
it 'responds with not found status' do
|
|
76
|
+
expect(response).to have_http_status(:not_found)
|
|
77
|
+
end
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
80
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_examples 'simple crud for edit with block' do
|
|
4
|
+
describe 'GET #edit with a render block' do
|
|
5
|
+
include_context 'with authenticated user' if check_authenticate(:edit)
|
|
6
|
+
|
|
7
|
+
let!(:record) { model }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
make_policies_succeed(:edit, permissive: true) if check_authorize(:edit)
|
|
11
|
+
get :edit, params: with_route_params(record_param(:edit, record)), format: format_param(:edit)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if check_html(:edit)
|
|
15
|
+
include_examples 'simple crud renders template', :edit
|
|
16
|
+
else
|
|
17
|
+
it 'renders the record through the block' do
|
|
18
|
+
expect(response).to render_or_redirect
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_examples 'simple crud for edit with finder' do
|
|
4
|
+
describe 'GET #edit with a custom finder' do
|
|
5
|
+
include_context 'with authenticated user' if check_authenticate(:edit)
|
|
6
|
+
|
|
7
|
+
context 'when the model exists' do
|
|
8
|
+
before do
|
|
9
|
+
model
|
|
10
|
+
make_policies_succeed(:edit, permissive: check_block(:edit)) if check_authorize(:edit)
|
|
11
|
+
get :edit, params: with_route_params(finder_key => model.public_send(finder_key)),
|
|
12
|
+
format: format_param(:edit)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
if check_block(:edit)
|
|
16
|
+
it 'finds the asked model' do
|
|
17
|
+
expect(rendered_record.id).to eq(model.id)
|
|
18
|
+
end
|
|
19
|
+
elsif check_html(:edit)
|
|
20
|
+
include_examples 'simple crud renders template', :edit
|
|
21
|
+
else
|
|
22
|
+
it 'responds with ok status' do
|
|
23
|
+
expect(response).to have_http_status(:ok)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'returns the asked model' do
|
|
27
|
+
expect(response_body['id']).to eq(model.id)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
include_examples 'simple crud not found with finder', :get, :edit
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
RSpec.shared_examples 'simple crud for index with scope' do
|
|
4
4
|
let(:request_params) { {} }
|
|
5
5
|
let(:my_models) { create_records(model_class, 2, scoped_attributes) }
|
|
6
|
-
let(:other_models) { create_records(model_class, 3, other_scoped_attributes) }
|
|
6
|
+
let(:other_models) { create_records(model_class, 3, other_scoped_attributes) if other_scoped_attributes }
|
|
7
|
+
let(:listed_ids) do
|
|
8
|
+
if check_html(:index)
|
|
9
|
+
rendered_records.map(&:id)
|
|
10
|
+
else
|
|
11
|
+
(check_paginate(:index) ? response_body['page'] : response_body).map { |m| m['id'] }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
7
14
|
|
|
8
15
|
# Hooks stay inside this context so co-including the example never
|
|
9
16
|
# authenticates or stubs policies for sibling examples.
|
|
@@ -16,17 +23,13 @@ RSpec.shared_examples 'simple crud for index with scope' do
|
|
|
16
23
|
get :index, params: with_route_params(request_params), format: format_param(:index)
|
|
17
24
|
end
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
it 'returns
|
|
25
|
-
expect(
|
|
26
|
-
end
|
|
27
|
-
else
|
|
28
|
-
it 'returns only the unpaginated scoped records' do
|
|
29
|
-
expect(response_body.map { |m| m['id'] }).to match_array(my_models.map(&:id))
|
|
26
|
+
it 'returns the scoped records' do
|
|
27
|
+
expect(listed_ids).to match_array(my_models.map(&:id))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if scoped_order
|
|
31
|
+
it 'returns the scoped records in order' do
|
|
32
|
+
expect(listed_ids).to eq(instance_exec(my_models, &scoped_order).map(&:id))
|
|
30
33
|
end
|
|
31
34
|
end
|
|
32
35
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# For a parent: controller. The parent in route_params must match the record's owner_association.
|
|
4
|
+
RSpec.shared_examples 'simple crud for nested resource' do
|
|
5
|
+
describe 'parent: scoping' do
|
|
6
|
+
include_context 'with authenticated user' if check_authenticate(:show)
|
|
7
|
+
|
|
8
|
+
it 'finds a record inside the parent' do
|
|
9
|
+
get :show, params: with_route_params(record_param(:show, model)), format: format_param(:show)
|
|
10
|
+
|
|
11
|
+
expect(response).to have_http_status(:ok)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'returns not found for a record outside the parent' do
|
|
15
|
+
outside = create_record(model_class, model_attributes.merge(owner_association => other_user))
|
|
16
|
+
get :show, params: with_route_params(record_param(:show, outside)), format: format_param(:show)
|
|
17
|
+
|
|
18
|
+
expect(response).to have_http_status(:not_found)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -5,7 +5,7 @@ RSpec.shared_examples 'simple crud for new with block' do
|
|
|
5
5
|
include_context 'with authenticated user' if check_authenticate(:new)
|
|
6
6
|
|
|
7
7
|
before do
|
|
8
|
-
make_policies_succeed(:new) if check_authorize(:new)
|
|
8
|
+
make_policies_succeed(:new, permissive: true) if check_authorize(:new)
|
|
9
9
|
get :new, params: with_route_params({}), format: format_param(:new)
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -8,11 +8,17 @@ RSpec.shared_examples 'simple crud for new with build' do
|
|
|
8
8
|
get :new, params: with_route_params({}), format: format_param(:new)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
if owner_association
|
|
12
|
+
it 'builds the record owned by the current user', :aggregate_failures do
|
|
13
|
+
if check_html(:new) || check_block(:new)
|
|
14
|
+
expect(rendered_record.public_send(owner_foreign_key)).to eq(current_user.id)
|
|
15
|
+
else
|
|
16
|
+
expect(response_body[owner_foreign_key.to_s]).to eq(current_user.id)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
it 'builds the record through the hook' do
|
|
21
|
+
expect(response).to be_successful
|
|
16
22
|
end
|
|
17
23
|
end
|
|
18
24
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Include alongside the per-action examples for a controller using owned_by:.
|
|
4
|
+
RSpec.shared_examples 'simple crud for owned resource' do
|
|
5
|
+
describe 'owned_by: scoping' do
|
|
6
|
+
include_context 'with authenticated user'
|
|
7
|
+
|
|
8
|
+
let!(:someone_elses_model) do
|
|
9
|
+
create_record(model_class, model_attributes.merge(owner_association => other_user))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'returns not found for a record owned by another user' do
|
|
13
|
+
get :show, params: with_route_params(record_param(:show, someone_elses_model)), format: format_param(:show)
|
|
14
|
+
|
|
15
|
+
expect(response).to have_http_status(:not_found)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'when updating a record owned by another user' do
|
|
19
|
+
let!(:original_value) { required_attribute && someone_elses_model.public_send(required_attribute) }
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
params = with_route_params(record_param(:update, someone_elses_model)).merge(body_params(model_params))
|
|
23
|
+
patch :update, params: params, format: format_param(:update)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'responds with not found' do
|
|
27
|
+
expect(response).to have_http_status(:not_found)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if required_attribute
|
|
31
|
+
it 'leaves the record untouched' do
|
|
32
|
+
expect(someone_elses_model.reload.public_send(required_attribute)).to eq(original_value)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'attributes a created record to the current user regardless of the request', :aggregate_failures do
|
|
38
|
+
body = body_params(model_params.merge(owner_association => other_user.id))
|
|
39
|
+
post :create, params: with_route_params(body), format: format_param(:create)
|
|
40
|
+
|
|
41
|
+
expect(response).to have_http_status(check_status(:create) || :created)
|
|
42
|
+
expect(model_class_object.last.public_send(owner_association)).to eq(current_user)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -39,16 +39,18 @@ RSpec.shared_examples 'simple crud for show' do
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
unless singular
|
|
43
|
+
describe 'when the model does not exist' do
|
|
44
|
+
include_context 'with authenticated user'
|
|
45
|
+
let(:show_params) { record_param(:show, nil, not_found: true) }
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
before do
|
|
48
|
+
show_request
|
|
49
|
+
end
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
it 'responds with not found status' do
|
|
52
|
+
expect(response).to have_http_status(:not_found)
|
|
53
|
+
end
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
end
|
|
@@ -7,7 +7,7 @@ RSpec.shared_examples 'simple crud for show with block' do
|
|
|
7
7
|
let!(:record) { model }
|
|
8
8
|
|
|
9
9
|
before do
|
|
10
|
-
make_policies_succeed(:show) if check_authorize(:show)
|
|
10
|
+
make_policies_succeed(:show, permissive: true) if check_authorize(:show)
|
|
11
11
|
get :show, params: with_route_params(record_param(:show, record)), format: format_param(:show)
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -61,24 +61,26 @@ RSpec.shared_examples 'simple crud for update' do
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
unless singular
|
|
65
|
+
context 'when updating a model that doesn\'t exist' do
|
|
66
|
+
include_context 'with authenticated user'
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
before do
|
|
69
|
+
put :update, params: with_route_params(record_param(:update, nil, not_found: true)),
|
|
70
|
+
format: format_param(:update)
|
|
71
|
+
end
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
it 'response with 404 status code' do
|
|
74
|
+
expect(response).to have_http_status(:not_found)
|
|
75
|
+
end
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
it 'doesn\'t create an model' do
|
|
78
|
+
expect(model_class_object.count).to be 0
|
|
79
|
+
end
|
|
78
80
|
end
|
|
79
81
|
end
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
if invalid_case?(:update)
|
|
82
84
|
context 'when updating with invalid attributes' do
|
|
83
85
|
include_context 'with authenticated user' if check_authenticate(:update)
|
|
84
86
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_examples 'simple crud for update with block' do
|
|
4
|
+
describe 'PUT #update with a render block' do
|
|
5
|
+
include_context 'with authenticated user' if check_authenticate(:update)
|
|
6
|
+
|
|
7
|
+
let!(:record) { model }
|
|
8
|
+
|
|
9
|
+
context 'when successfully updating a record' do
|
|
10
|
+
before do
|
|
11
|
+
make_policies_succeed(:update, permissive: true) if check_authorize(:update)
|
|
12
|
+
put :update, params: with_route_params(body_params(model_params).merge(record_param(:update, record))),
|
|
13
|
+
format: format_param(:update)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'passes the saved record to the block' do
|
|
17
|
+
expect(response).to render_or_redirect
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'updates the record' do
|
|
21
|
+
expect(record.reload).to have_attributes(model_params)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if invalid_case?(:update)
|
|
26
|
+
context 'when updating with invalid attributes' do
|
|
27
|
+
before do
|
|
28
|
+
make_policies_succeed(:update, permissive: true) if check_authorize(:update)
|
|
29
|
+
put :update, params: with_route_params(body_params({ required_attribute => nil }.merge(owner_params))
|
|
30
|
+
.merge(record_param(:update, record))),
|
|
31
|
+
format: format_param(:update)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'does not change the record' do
|
|
35
|
+
expect(record.reload.public_send(required_attribute)).not_to be_nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -5,8 +5,9 @@ RSpec.shared_examples 'simple crud for update with finder' do
|
|
|
5
5
|
include_context 'with authenticated user' if check_authenticate(:update)
|
|
6
6
|
|
|
7
7
|
context 'when successfully updating a model' do
|
|
8
|
+
let(:updated_attributes) { required_attribute ? { required_attribute => 'Updated' } : model_params }
|
|
8
9
|
let(:update_params) do
|
|
9
|
-
with_route_params(body_params(
|
|
10
|
+
with_route_params(body_params(updated_attributes).merge(owner_params))
|
|
10
11
|
.merge(finder_key => model.public_send(finder_key))
|
|
11
12
|
end
|
|
12
13
|
|
|
@@ -15,13 +16,15 @@ RSpec.shared_examples 'simple crud for update with finder' do
|
|
|
15
16
|
put :update, params: update_params, format: format_param(:update)
|
|
16
17
|
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
if required_attribute
|
|
20
|
+
it 'updates the model' do
|
|
21
|
+
expect(model.reload.public_send(required_attribute)).to eq('Updated')
|
|
22
|
+
end
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
if check_block(:update)
|
|
23
26
|
it 'passes the updated model to the block' do
|
|
24
|
-
expect(
|
|
27
|
+
expect(response).to render_or_redirect
|
|
25
28
|
end
|
|
26
29
|
elsif check_html(:update)
|
|
27
30
|
it 'redirects to the updated record' do
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
RSpec.shared_examples 'simple crud not found with finder' do |http_method, action|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
unless singular
|
|
5
|
+
context 'when the model does not exist' do
|
|
6
|
+
before do
|
|
7
|
+
send(http_method, action, params: with_route_params(finder_key => "nonexistent-#{finder_key}"),
|
|
8
|
+
format: format_param(action))
|
|
9
|
+
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
it 'responds with not found status' do
|
|
12
|
+
expect(response).to have_http_status(:not_found)
|
|
13
|
+
end
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe BlockCreateRedirect::DummyModelsController, type: :controller do
|
|
6
|
+
include_examples 'simple crud for create with block'
|
|
7
|
+
|
|
8
|
+
describe 'without a validated attribute', simple_crud: { required_attribute: nil } do
|
|
9
|
+
include_examples 'simple crud for create with block'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -4,6 +4,8 @@ require 'spec_helper'
|
|
|
4
4
|
|
|
5
5
|
describe BlockFinder::DummyModelsController, type: :controller do
|
|
6
6
|
include_examples 'simple crud for edit'
|
|
7
|
+
include_examples 'simple crud for edit with finder'
|
|
8
|
+
include_examples 'simple crud for edit with block'
|
|
7
9
|
include_examples 'simple crud for show with finder'
|
|
8
10
|
include_examples 'simple crud for update with finder'
|
|
9
11
|
include_examples 'simple crud for destroy with finder'
|