wor-simple_crud 0.3.0 → 0.3.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 +4 -4
- data/.gitignore +5 -0
- data/CHANGELOG.md +16 -2
- data/README.md +57 -14
- data/lib/simple_crud/action_lambdas.rb +81 -0
- data/lib/simple_crud/controller_helpers.rb +11 -2
- data/lib/simple_crud/rspec/config.rb +18 -5
- data/lib/simple_crud/rspec/helpers/authentication.rb +32 -0
- data/lib/simple_crud/rspec/helpers/controller_options.rb +19 -0
- data/lib/simple_crud/rspec/helpers/models.rb +55 -0
- data/lib/simple_crud/rspec/helpers/policies.rb +25 -0
- data/lib/simple_crud/rspec/helpers/requests.rb +45 -0
- data/lib/simple_crud/rspec/helpers/settings.rb +49 -0
- data/lib/simple_crud/rspec/helpers.rb +16 -138
- data/lib/simple_crud/rspec.rb +1 -0
- data/lib/simple_crud/simple_crud_controller.rb +11 -74
- data/lib/simple_crud/version.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_create.rb +15 -12
- data/lib/spec/shared_examples/simple_crud_for_create_with_block.rb +25 -7
- data/lib/spec/shared_examples/simple_crud_for_create_with_build.rb +2 -2
- data/lib/spec/shared_examples/simple_crud_for_destroy.rb +25 -0
- data/lib/spec/shared_examples/simple_crud_for_destroy_with_block.rb +10 -2
- data/lib/spec/shared_examples/simple_crud_for_destroy_with_finder.rb +17 -6
- data/lib/spec/shared_examples/simple_crud_for_edit.rb +79 -0
- data/lib/spec/shared_examples/simple_crud_for_index.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_index_with_block.rb +11 -3
- data/lib/spec/shared_examples/simple_crud_for_index_with_scope.rb +25 -13
- data/lib/spec/shared_examples/simple_crud_for_new.rb +1 -1
- data/lib/spec/shared_examples/simple_crud_for_new_with_block.rb +13 -2
- data/lib/spec/shared_examples/simple_crud_for_new_with_build.rb +10 -4
- data/lib/spec/shared_examples/simple_crud_for_show_with_block.rb +13 -2
- data/lib/spec/shared_examples/simple_crud_for_show_with_finder.rb +16 -7
- data/lib/spec/shared_examples/simple_crud_for_update.rb +16 -9
- data/lib/spec/shared_examples/simple_crud_for_update_with_finder.rb +16 -6
- data/lib/spec/shared_examples/simple_crud_not_found_with_finder.rb +2 -1
- data/spec/block_finder/dummy_models_controller_spec.rb +10 -0
- data/spec/block_json/dummy_models_controller_spec.rb +9 -0
- data/spec/block_redirect/dummy_models_controller_spec.rb +7 -0
- data/spec/dummy/app/controllers/block_finder/dummy_models_controller.rb +25 -0
- data/spec/dummy/app/controllers/block_json/dummy_models_controller.rb +17 -0
- data/spec/dummy/app/controllers/block_redirect/dummy_models_controller.rb +13 -0
- data/spec/dummy/app/controllers/finder/dummy_models_controller.rb +1 -0
- data/spec/dummy/app/controllers/html_finder/dummy_models_controller.rb +17 -0
- data/spec/dummy/app/controllers/html_scoped/dummy_models_controller.rb +1 -1
- data/spec/dummy/app/controllers/unpaginated_scoped/dummy_models_controller.rb +16 -0
- data/spec/dummy/app/models/dummy_model_policy.rb +5 -1
- data/spec/dummy/app/views/html_finder/dummy_models/edit.html.erb +1 -0
- data/spec/dummy/app/views/html_finder/dummy_models/new.html.erb +1 -0
- data/spec/dummy/app/views/html_finder/dummy_models/show.html.erb +1 -0
- data/spec/dummy/config/routes.rb +21 -1
- data/spec/dummy_model_policy_spec.rb +18 -8
- data/spec/finder/dummy_models_controller_spec.rb +1 -0
- data/spec/html_finder/dummy_models_controller_spec.rb +11 -0
- data/spec/html_scoped/dummy_models_controller_spec.rb +1 -1
- data/spec/scoped_params/dummy_models_controller_spec.rb +4 -3
- data/spec/simple_crud/rspec_config_spec.rb +33 -0
- data/spec/unpaginated_scoped/dummy_models_controller_spec.rb +7 -0
- metadata +23 -2
|
@@ -1,147 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'helpers/settings'
|
|
4
|
+
require_relative 'helpers/controller_options'
|
|
5
|
+
require_relative 'helpers/models'
|
|
6
|
+
require_relative 'helpers/authentication'
|
|
7
|
+
require_relative 'helpers/requests'
|
|
8
|
+
require_relative 'helpers/policies'
|
|
9
|
+
|
|
3
10
|
module SimpleCrud
|
|
4
11
|
module RSpec
|
|
5
12
|
# Helpers available to the shared examples (and to apps that include
|
|
6
|
-
# them)
|
|
7
|
-
#
|
|
13
|
+
# them), composed from focused sub-modules: settings resolution,
|
|
14
|
+
# controller-option introspection, record building, authentication,
|
|
15
|
+
# request params and policy access.
|
|
8
16
|
module Helpers
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# :unprocessable_entity was renamed :unprocessable_content in Rack 3.1.
|
|
18
|
-
# Resolve the current Rack's canonical symbol for 422.
|
|
19
|
-
def unprocessable_status
|
|
20
|
-
Rack::Utils::SYMBOL_TO_STATUS_CODE.invert[422]
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
%i[paginate authorize authenticate serializer html finder scope build raise_on_invalid].each do |option|
|
|
24
|
-
define_method("check_#{option}") { |method| get_option(method, option) }
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
%i[owner_association required_attribute required_error finder_key params_key invalid_status
|
|
28
|
-
unauthenticated_status assert_html_template].each do |setting|
|
|
29
|
-
define_method(setting) { resolve(config.public_send(setting)) }
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def model_class
|
|
33
|
-
described_class.to_s.split('::')
|
|
34
|
-
.last.sub('Controller', '').singularize.underscore
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def model_class_object
|
|
38
|
-
model_class.classify.constantize
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def model
|
|
42
|
-
@model ||= create_record(model_class, model_attributes)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def model_attributes
|
|
46
|
-
association = resolve(config.owner_association)
|
|
47
|
-
association ? { association => current_user } : {}
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def create_record(klass, attributes)
|
|
51
|
-
instance_exec(klass, attributes, &config.create_record)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def create_records(klass, count, attributes)
|
|
55
|
-
instance_exec(klass, count, attributes, &config.create_records)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def params_for(klass)
|
|
59
|
-
instance_exec(klass, &config.params_for)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def model_params
|
|
63
|
-
@model_params ||= params_for(model_class)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def current_user
|
|
67
|
-
@current_user ||= instance_exec(&config.current_user)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def authenticate_request
|
|
71
|
-
instance_exec(&config.authenticate)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def owner_foreign_key
|
|
75
|
-
:"#{owner_association}_id"
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# The owner association attributed to current_user, if the model has one.
|
|
79
|
-
def owner_params
|
|
80
|
-
owner_association ? { owner_foreign_key => current_user.id } : {}
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Extra params (e.g. a parent slug) added to every request, for nested
|
|
84
|
-
# resources like /classrooms/:classroom_slug/assignments.
|
|
85
|
-
def route_params
|
|
86
|
-
resolve(config.route_params)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def with_route_params(attrs)
|
|
90
|
-
route_params.merge(attrs)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# The params that identify a record for the given action, using the
|
|
94
|
-
# configured finder_key when the action has a custom finder.
|
|
95
|
-
def record_param(action, record, not_found: false)
|
|
96
|
-
key = check_finder(action) ? finder_key : :id
|
|
97
|
-
value = not_found ? "nonexistent-#{key}" : record.public_send(key)
|
|
98
|
-
{ key => value }
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Wraps a request body under the model's strong-params key when
|
|
102
|
-
# params_key is configured (nested strong params), else passes it flat.
|
|
103
|
-
def body_params(attrs)
|
|
104
|
-
key = params_key
|
|
105
|
-
key ? { key => attrs } : attrs
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def policy_class_object
|
|
109
|
-
instance_exec(model_class_object, &config.policy_class)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def model_serializer
|
|
113
|
-
defined?(serializer) ? serializer : instance_exec(model, &config.serializer_class)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def make_policies_fail(method)
|
|
117
|
-
allow(policy_class_object).to receive(:new)
|
|
118
|
-
.and_return(instance_double(policy_class_object, "#{method}?" => false))
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def make_policies_succeed(method)
|
|
122
|
-
allow(policy_class_object).to receive(:new)
|
|
123
|
-
.and_return(instance_double(policy_class_object, "#{method}?" => true))
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def request_format(action)
|
|
127
|
-
check_html(action) ? :html : :json
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def resolve(value)
|
|
131
|
-
value.is_a?(Proc) ? instance_exec(&value) : value
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Runs the block with a config setting temporarily overridden, restoring
|
|
135
|
-
# the original value afterwards (even if the block raises). Useful when
|
|
136
|
-
# a controller's spec needs a different setting than the app-wide default.
|
|
137
|
-
def with_config_override(setting, value)
|
|
138
|
-
config_instance = SimpleCrud::RSpec::Config.instance
|
|
139
|
-
original = config_instance.public_send(setting)
|
|
140
|
-
SimpleCrud::RSpec.configure { |c| c.public_send("#{setting}=", value) }
|
|
141
|
-
yield
|
|
142
|
-
ensure
|
|
143
|
-
SimpleCrud::RSpec.configure { |c| c.public_send("#{setting}=", original) }
|
|
144
|
-
end
|
|
17
|
+
include Settings
|
|
18
|
+
include ControllerOptions
|
|
19
|
+
include Models
|
|
20
|
+
include Authentication
|
|
21
|
+
include Requests
|
|
22
|
+
include Policies
|
|
145
23
|
end
|
|
146
24
|
end
|
|
147
25
|
end
|
data/lib/simple_crud/rspec.rb
CHANGED
|
@@ -10,6 +10,7 @@ require_relative '../spec/shared_examples/simple_crud_for_index'
|
|
|
10
10
|
require_relative '../spec/shared_examples/simple_crud_for_destroy'
|
|
11
11
|
require_relative '../spec/shared_examples/simple_crud_for_create'
|
|
12
12
|
require_relative '../spec/shared_examples/simple_crud_for_new'
|
|
13
|
+
require_relative '../spec/shared_examples/simple_crud_for_edit'
|
|
13
14
|
require_relative '../spec/shared_examples/unauthorized_when_not_logged_in'
|
|
14
15
|
require_relative '../spec/shared_examples/simple_crud_renders_template'
|
|
15
16
|
require_relative '../spec/shared_examples/simple_crud_without_authenticated_user'
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
require 'active_support/all'
|
|
4
4
|
require_relative 'config'
|
|
5
5
|
require_relative 'controller_helpers'
|
|
6
|
+
require_relative 'action_lambdas'
|
|
6
7
|
|
|
7
8
|
# Extended onto a controller for CRUD actions.
|
|
8
9
|
module SimpleCrudController
|
|
9
10
|
extend SimpleCrud::ControllerHelpers
|
|
11
|
+
# Include, not extend: controllers gain these by extending SimpleCrudController.
|
|
12
|
+
include SimpleCrud::ActionLambdas
|
|
10
13
|
|
|
11
14
|
cattr_accessor :params, :permitted
|
|
12
15
|
|
|
@@ -15,15 +18,16 @@ module SimpleCrudController
|
|
|
15
18
|
### paginate: paginate the list via Config.pagination_adapter (wor-paginate by default)
|
|
16
19
|
### authenticate: use devise to authenticate
|
|
17
20
|
### serializer: use a particular serializer (both each_serializer and serializer)
|
|
18
|
-
### html: render the action's ERB template instead of JSON (index/show/new/create/update/destroy)
|
|
19
|
-
### finder: custom record lookup (Proc/lambda or Symbol) for :show/:update/:destroy
|
|
21
|
+
### html: render the action's ERB template instead of JSON (index/show/new/edit/create/update/destroy)
|
|
22
|
+
### finder: custom record lookup (Proc/lambda or Symbol) for :show/:update/:destroy/:edit
|
|
20
23
|
### scope: custom index scope (Proc/lambda taking current_user and optional params), overrides policy_scope
|
|
21
24
|
### build: custom record builder (Proc/lambda) for :new/:create, invoked with the controller as self
|
|
22
25
|
### raise_on_invalid: use strict create!/update! semantics instead of returning 422
|
|
23
26
|
### A block given to simple_crud_for renders explicitly: it receives the records for :index,
|
|
24
|
-
### the record for :show/:new, or the record and a saved flag for :create/:update/:destroy
|
|
27
|
+
### the record for :show/:new/:edit, or the record and a saved flag for :create/:update/:destroy
|
|
25
28
|
def simple_crud_for(method, parameters = {}, &block)
|
|
26
29
|
parameters[:html] = true if block && !parameters.key?(:html)
|
|
30
|
+
parameters[:block] = true if block
|
|
27
31
|
parameters = parameters_with_defaults(parameters)
|
|
28
32
|
klass = simple_crud_controller_model
|
|
29
33
|
check_valid_method(method)
|
|
@@ -47,77 +51,12 @@ module SimpleCrudController
|
|
|
47
51
|
@simple_crud_metadata[method] = parameters
|
|
48
52
|
end
|
|
49
53
|
|
|
50
|
-
def crud_lambda_for_show(klass, parameters = {}, &block)
|
|
51
|
-
lambda do
|
|
52
|
-
authenticate_user! if parameters[:authenticate]
|
|
53
|
-
requested = SimpleCrudController.find_record(klass, self, parameters)
|
|
54
|
-
|
|
55
|
-
options = {}.merge(serializer: parameters[:serializer]).compact
|
|
56
|
-
SimpleCrudController.maybe_authorize(self, requested, parameters)
|
|
57
|
-
SimpleCrudController.render_show(self, requested, options, parameters, &block)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def crud_lambda_for_new(klass, parameters = {}, &block)
|
|
62
|
-
lambda do
|
|
63
|
-
authenticate_user! if parameters[:authenticate]
|
|
64
|
-
record = SimpleCrudController.build_record(self, klass, parameters)
|
|
65
|
-
SimpleCrudController.maybe_authorize(self, record, parameters)
|
|
66
|
-
SimpleCrudController.render_new(self, record, parameters, &block)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def crud_lambda_for_index(klass, parameters = {}, &block)
|
|
71
|
-
lambda do
|
|
72
|
-
authenticate_user! if parameters[:authenticate]
|
|
73
|
-
SimpleCrudController.maybe_authorize(self, klass.new, parameters)
|
|
74
|
-
options = {}.merge(each_serializer: parameters[:serializer]).compact
|
|
75
|
-
SimpleCrudController.render_index(self, klass, options, parameters, &block)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def crud_lambda_for_create(klass, parameters = {}, &block)
|
|
80
|
-
lambda do
|
|
81
|
-
authenticate_user! if parameters[:authenticate]
|
|
82
|
-
permitted_params = send("#{self.class.simple_crud_controller_model.to_s.underscore}_params")
|
|
83
|
-
record = SimpleCrudController.build_record(self, klass, parameters)
|
|
84
|
-
record.assign_attributes(permitted_params)
|
|
85
|
-
SimpleCrudController.maybe_authorize(self, record, parameters)
|
|
86
|
-
persist = ->(bang:) { bang ? record.save! : record.save }
|
|
87
|
-
options = { status: :created, failure_template: :new }
|
|
88
|
-
SimpleCrudController.save_and_render(self, record, parameters, options, persist, &block)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def crud_lambda_for_update(klass, parameters = {}, &block)
|
|
93
|
-
lambda do
|
|
94
|
-
authenticate_user! if parameters[:authenticate]
|
|
95
|
-
requested = SimpleCrudController.find_record(klass, self, parameters)
|
|
96
|
-
SimpleCrudController.maybe_authorize(self, requested, parameters)
|
|
97
|
-
permitted_params = send("#{self.class.simple_crud_controller_model.to_s.underscore}_params")
|
|
98
|
-
persist = ->(bang:) { bang ? requested.update!(permitted_params) : requested.update(permitted_params) }
|
|
99
|
-
options = { status: :ok, failure_template: :edit }
|
|
100
|
-
SimpleCrudController.save_and_render(self, requested, parameters, options, persist, &block)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def crud_lambda_for_destroy(klass, parameters = {}, &block)
|
|
105
|
-
lambda do
|
|
106
|
-
authenticate_user! if parameters[:authenticate]
|
|
107
|
-
requested = SimpleCrudController.find_record(klass, self, parameters)
|
|
108
|
-
SimpleCrudController.maybe_authorize(self, requested, parameters)
|
|
109
|
-
options = { status: :ok, failure_template: :show, redirect: parameters[:redirect] || klass }
|
|
110
|
-
persist = ->(bang:) { bang ? requested.destroy! : requested.destroy }
|
|
111
|
-
SimpleCrudController.persist_and_render(self, requested, parameters, options, persist, &block)
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
54
|
def simple_crud_controller_model
|
|
116
55
|
to_s.split('::').last.sub('Controller', '').singularize.classify.constantize
|
|
117
56
|
end
|
|
118
57
|
|
|
119
58
|
def check_valid_method(method)
|
|
120
|
-
raise ArgumentError, 'invalid method' unless %i[show index create update destroy new].include? method
|
|
59
|
+
raise ArgumentError, 'invalid method' unless %i[show index create update destroy new edit].include? method
|
|
121
60
|
end
|
|
122
61
|
|
|
123
62
|
def check_policies(parameters)
|
|
@@ -130,11 +69,9 @@ module SimpleCrudController
|
|
|
130
69
|
end
|
|
131
70
|
|
|
132
71
|
def check_serializer(parameters)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
serializer_name = parameters[:serializer].to_s
|
|
136
|
-
return if Kernel.const_defined?(serializer_name)
|
|
72
|
+
name = parameters[:serializer].to_s
|
|
73
|
+
return if name.blank? || Kernel.const_defined?(name)
|
|
137
74
|
|
|
138
|
-
raise ArgumentError, "create a valid serializer with name #{
|
|
75
|
+
raise ArgumentError, "create a valid serializer with name #{name}"
|
|
139
76
|
end
|
|
140
77
|
end
|
data/lib/simple_crud/version.rb
CHANGED
|
@@ -47,8 +47,9 @@ shared_examples 'simple crud for create' do
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
it 'creates the record' do
|
|
50
|
+
it 'creates the record', :aggregate_failures do
|
|
51
51
|
expect(model_class_object.count).to be 1
|
|
52
|
+
instance_exec(model_class_object.last, &created_record_check) if created_record_check
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
|
|
@@ -60,20 +61,22 @@ shared_examples 'simple crud for create' do
|
|
|
60
61
|
post :create, params: with_route_params(body_params(owner_params)), format: request_format(:create)
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
unless check_block(:create)
|
|
65
|
+
if check_html(:create)
|
|
66
|
+
include_examples 'simple crud renders template', :new, -> { invalid_status }
|
|
67
|
+
else
|
|
68
|
+
it 'responds with unprocessable entity' do
|
|
69
|
+
expect(response).to have_http_status(unprocessable_status)
|
|
70
|
+
end
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
it 'returns the validation errors' do
|
|
73
|
+
expect(response_body['errors']).to include(required_error)
|
|
74
|
+
end
|
|
72
75
|
end
|
|
76
|
+
end
|
|
73
77
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
end
|
|
78
|
+
it 'does not create a model' do
|
|
79
|
+
expect(model_class_object.count).to be 0
|
|
77
80
|
end
|
|
78
81
|
end
|
|
79
82
|
end
|
|
@@ -2,17 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
shared_examples 'simple crud for create with block' do
|
|
4
4
|
describe 'POST #create with a render block' do
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
context 'when successfully creating a record' do
|
|
6
|
+
include_context 'with authenticated user' if check_authenticate(:create)
|
|
7
|
+
let(:create_params) { model_params.merge(owner_params) }
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
before do
|
|
10
|
+
post :create, params: with_route_params(body_params(create_params)), format: request_format(:create)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'passes the saved record to the block' do
|
|
14
|
+
expect(response).to be_successful
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'creates the record' do
|
|
18
|
+
expect(model_class_object.count).to be 1
|
|
19
|
+
end
|
|
9
20
|
end
|
|
10
21
|
|
|
11
|
-
|
|
12
|
-
|
|
22
|
+
unless check_raise_on_invalid(:create)
|
|
23
|
+
context 'when creating with invalid attributes' do
|
|
24
|
+
include_context 'with authenticated user' if check_authenticate(:create)
|
|
25
|
+
|
|
26
|
+
before do
|
|
27
|
+
post :create, params: with_route_params(body_params(owner_params)), format: request_format(:create)
|
|
28
|
+
end
|
|
13
29
|
|
|
14
|
-
|
|
15
|
-
|
|
30
|
+
it 'does not create a model' do
|
|
31
|
+
expect(model_class_object.count).to be 0
|
|
32
|
+
end
|
|
33
|
+
end
|
|
16
34
|
end
|
|
17
35
|
end
|
|
18
36
|
end
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
shared_examples 'simple crud for create with build' do
|
|
4
4
|
describe 'POST #create with a build hook' do
|
|
5
|
-
include_context 'with authenticated user'
|
|
5
|
+
include_context 'with authenticated user' if check_authenticate(:create)
|
|
6
6
|
|
|
7
7
|
before do
|
|
8
|
-
post :create, params: with_route_params(body_params(
|
|
8
|
+
post :create, params: with_route_params(body_params(params_for(model_class))), format: request_format(:create)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
it 'creates the record owned by the current user' do
|
|
@@ -46,6 +46,31 @@ shared_examples 'simple crud for destroy' do
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
context 'when destroying fails' do
|
|
50
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
51
|
+
|
|
52
|
+
before do
|
|
53
|
+
model
|
|
54
|
+
allow(model).to receive(:destroy).and_return(false)
|
|
55
|
+
allow(SimpleCrudController).to receive(:find_record).and_return(model)
|
|
56
|
+
delete :destroy, params: with_route_params(record_param(:destroy, model)), format: request_format(:destroy)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'keeps the record' do
|
|
60
|
+
expect(model_class_object.exists?(model.id)).to be true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
unless check_block(:destroy) || check_raise_on_invalid(:destroy)
|
|
64
|
+
if check_html(:destroy)
|
|
65
|
+
include_examples 'simple crud renders template', :show
|
|
66
|
+
else
|
|
67
|
+
it 'responds with unprocessable entity' do
|
|
68
|
+
expect(response).to have_http_status(unprocessable_status)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
49
74
|
context 'when ID is invalid' do
|
|
50
75
|
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
51
76
|
|
|
@@ -2,12 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
shared_examples 'simple crud for destroy with block' do
|
|
4
4
|
describe 'DELETE #destroy with a render block' do
|
|
5
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
6
|
+
|
|
5
7
|
let!(:record) { model }
|
|
6
8
|
|
|
7
|
-
before
|
|
9
|
+
before do
|
|
10
|
+
delete :destroy, params: with_route_params(record_param(:destroy, record)), format: request_format(:destroy)
|
|
11
|
+
end
|
|
8
12
|
|
|
9
13
|
it 'passes the destroyed record to the block' do
|
|
10
|
-
expect(response
|
|
14
|
+
expect(response).to be_successful
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'destroys the record' do
|
|
18
|
+
expect(model_class_object.exists?(record.id)).to be false
|
|
11
19
|
end
|
|
12
20
|
end
|
|
13
21
|
end
|
|
@@ -2,21 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
shared_examples 'simple crud for destroy with finder' do
|
|
4
4
|
describe 'DELETE #destroy with a custom finder' do
|
|
5
|
-
include_context 'with authenticated user'
|
|
5
|
+
include_context 'with authenticated user' if check_authenticate(:destroy)
|
|
6
6
|
|
|
7
7
|
context 'when the model exists' do
|
|
8
8
|
before do
|
|
9
9
|
model
|
|
10
|
-
delete :destroy, params: with_route_params(finder_key => model.public_send(finder_key))
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
it 'responds with ok status' do
|
|
14
|
-
expect(response).to have_http_status(:ok)
|
|
10
|
+
delete :destroy, params: with_route_params(finder_key => model.public_send(finder_key)),
|
|
11
|
+
format: request_format(:destroy)
|
|
15
12
|
end
|
|
16
13
|
|
|
17
14
|
it 'destroys the model' do
|
|
18
15
|
expect(model_class_object.exists?(model.id)).to be false
|
|
19
16
|
end
|
|
17
|
+
|
|
18
|
+
if check_block(:destroy)
|
|
19
|
+
it 'passes the destroyed record to the block' do
|
|
20
|
+
expect(rendered_record.id).to eq(model.id)
|
|
21
|
+
end
|
|
22
|
+
elsif check_html(:destroy)
|
|
23
|
+
it 'redirects to the collection' do
|
|
24
|
+
expect(response).to have_http_status(:found)
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
it 'responds with ok status' do
|
|
28
|
+
expect(response).to have_http_status(:ok)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
20
31
|
end
|
|
21
32
|
|
|
22
33
|
include_examples 'simple crud not found with finder', :delete, :destroy
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
shared_examples 'simple crud for edit' do
|
|
4
|
+
describe 'GET #edit' do
|
|
5
|
+
subject(:edit_request) { get :edit, params: with_route_params(edit_params), format: request_format(:edit) }
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
model
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context 'without authenticated user' do
|
|
12
|
+
subject!(:req) do
|
|
13
|
+
get :edit, params: with_route_params(record_param(:edit, model)), format: request_format(:edit)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
include_examples 'unauthorized when not logged in' if check_authenticate(:edit)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if check_authorize(:edit)
|
|
20
|
+
context 'when the user is not authorized' do
|
|
21
|
+
include_context 'with authenticated user' if check_authenticate(:edit)
|
|
22
|
+
|
|
23
|
+
let(:edit_params) { record_param(:edit, model) }
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
model
|
|
27
|
+
make_policies_fail(:edit)
|
|
28
|
+
edit_request
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'responds with forbidden status' do
|
|
32
|
+
expect(response).to have_http_status(:forbidden)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context 'when the model exists' do
|
|
38
|
+
include_context 'with authenticated user' if check_authenticate(:edit)
|
|
39
|
+
|
|
40
|
+
let(:edit_params) { record_param(:edit, model) }
|
|
41
|
+
|
|
42
|
+
before do
|
|
43
|
+
model
|
|
44
|
+
make_policies_succeed(:edit) if check_authorize(:edit)
|
|
45
|
+
edit_request
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'responds with ok status' do
|
|
49
|
+
expect(response).to have_http_status(:ok)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if check_block(:edit)
|
|
53
|
+
it 'renders the asked model through the block' do
|
|
54
|
+
expect(response).to be_successful
|
|
55
|
+
end
|
|
56
|
+
elsif check_html(:edit)
|
|
57
|
+
include_examples 'simple crud renders template', :edit
|
|
58
|
+
else
|
|
59
|
+
it 'returns the asked model' do
|
|
60
|
+
expect(response_body['id']).to eq(model.id)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'when the model does not exist' do
|
|
66
|
+
include_context 'with authenticated user'
|
|
67
|
+
|
|
68
|
+
let(:edit_params) { record_param(:edit, nil, not_found: true) }
|
|
69
|
+
|
|
70
|
+
before do
|
|
71
|
+
edit_request
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'responds with not found status' do
|
|
75
|
+
expect(response).to have_http_status(:not_found)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -13,7 +13,7 @@ shared_examples 'simple crud for index' do
|
|
|
13
13
|
include_context 'with authenticated user' if check_authenticate(:index)
|
|
14
14
|
|
|
15
15
|
before do
|
|
16
|
-
make_policies_succeed(:index)
|
|
16
|
+
make_policies_succeed(:index) if check_authorize(:index)
|
|
17
17
|
get :index, params: with_route_params({}), format: request_format(:index)
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
shared_examples 'simple crud for index with block' do
|
|
4
4
|
describe 'GET #index with a render block' do
|
|
5
|
-
let(:created_models) { create_records(model_class, 2,
|
|
5
|
+
let(:created_models) { create_records(model_class, 2, model_attributes) }
|
|
6
|
+
|
|
7
|
+
include_context 'with authenticated user' if check_authenticate(:index)
|
|
6
8
|
|
|
7
9
|
before do
|
|
8
10
|
created_models
|
|
9
|
-
get :index, params: with_route_params({}), format: :
|
|
11
|
+
get :index, params: with_route_params({}), format: request_format(:index)
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
if check_html(:index)
|
|
15
|
+
include_examples 'simple crud renders template', :index
|
|
16
|
+
else
|
|
17
|
+
it 'renders the records through the block' do
|
|
18
|
+
expect(response).to be_successful
|
|
19
|
+
end
|
|
20
|
+
end
|
|
13
21
|
end
|
|
14
22
|
end
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
shared_examples 'simple crud for index with scope' do
|
|
4
|
-
let(:user) { current_user }
|
|
5
|
-
let(:other_user) { resolve(config.other_user) }
|
|
6
|
-
let(:my_models) { create_records(model_class, 2, owner_association => user) }
|
|
7
|
-
let(:other_models) { create_records(model_class, 3, owner_association => other_user) }
|
|
8
4
|
let(:request_params) { {} }
|
|
5
|
+
let(:my_models) { create_records(model_class, 2, scoped_attributes) }
|
|
6
|
+
let(:other_models) { create_records(model_class, 3, other_scoped_attributes) }
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
# Hooks stay inside this context so co-including the example never
|
|
9
|
+
# authenticates or stubs policies for sibling examples.
|
|
10
|
+
context 'when listing the scoped records' do
|
|
11
|
+
before do
|
|
12
|
+
authenticate_request if check_authenticate(:index)
|
|
13
|
+
make_policies_succeed(:index) if check_authorize(:index)
|
|
14
|
+
my_models
|
|
15
|
+
other_models
|
|
16
|
+
get :index, params: with_route_params(request_params), format: request_format(:index)
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
if check_html(:index)
|
|
20
|
+
it 'returns only the assigned scoped records' do
|
|
21
|
+
expect(rendered_records.map(&:id)).to match_array(my_models.map(&:id))
|
|
22
|
+
end
|
|
23
|
+
elsif check_paginate(:index)
|
|
24
|
+
it 'returns only the paginated scoped records' do
|
|
25
|
+
expect(response_body['page'].map { |m| m['id'] }).to match_array(my_models.map(&:id))
|
|
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))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
20
32
|
end
|
|
21
33
|
end
|