wor-simple_crud 0.3.1 → 0.4.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +36 -12
  4. data/lib/simple_crud/rspec/helpers/controller_options.rb +6 -1
  5. data/lib/simple_crud/rspec/helpers/models.rb +16 -1
  6. data/lib/simple_crud/simple_crud_controller.rb +22 -7
  7. data/lib/simple_crud/version.rb +1 -1
  8. data/lib/simple_crud.rb +1 -0
  9. data/lib/spec/shared_examples/authorization_adapter_authorize.rb +1 -1
  10. data/lib/spec/shared_examples/simple_crud_for_create.rb +1 -1
  11. data/lib/spec/shared_examples/simple_crud_for_create_with_block.rb +1 -1
  12. data/lib/spec/shared_examples/simple_crud_for_create_with_build.rb +1 -1
  13. data/lib/spec/shared_examples/simple_crud_for_destroy.rb +1 -1
  14. data/lib/spec/shared_examples/simple_crud_for_destroy_with_block.rb +1 -1
  15. data/lib/spec/shared_examples/simple_crud_for_destroy_with_finder.rb +1 -1
  16. data/lib/spec/shared_examples/simple_crud_for_edit.rb +1 -1
  17. data/lib/spec/shared_examples/simple_crud_for_index.rb +1 -1
  18. data/lib/spec/shared_examples/simple_crud_for_index_with_block.rb +1 -1
  19. data/lib/spec/shared_examples/simple_crud_for_index_with_scope.rb +1 -1
  20. data/lib/spec/shared_examples/simple_crud_for_new.rb +1 -1
  21. data/lib/spec/shared_examples/simple_crud_for_new_with_block.rb +1 -1
  22. data/lib/spec/shared_examples/simple_crud_for_new_with_build.rb +1 -1
  23. data/lib/spec/shared_examples/simple_crud_for_show.rb +1 -1
  24. data/lib/spec/shared_examples/simple_crud_for_show_with_block.rb +1 -1
  25. data/lib/spec/shared_examples/simple_crud_for_show_with_finder.rb +1 -1
  26. data/lib/spec/shared_examples/simple_crud_for_update.rb +1 -1
  27. data/lib/spec/shared_examples/simple_crud_for_update_with_finder.rb +1 -1
  28. data/lib/spec/shared_examples/simple_crud_not_found_with_finder.rb +1 -1
  29. data/lib/spec/shared_examples/simple_crud_renders_template.rb +1 -1
  30. data/lib/spec/shared_examples/simple_crud_when_not_authorized.rb +1 -1
  31. data/lib/spec/shared_examples/simple_crud_without_authenticated_user.rb +1 -1
  32. data/lib/spec/shared_examples/unauthorized_when_not_logged_in.rb +1 -1
  33. data/spec/dummy/app/controllers/block/dummy_models_controller.rb +1 -6
  34. data/spec/dummy/app/controllers/block_new/dummy_models_controller.rb +1 -1
  35. data/spec/dummy/app/controllers/block_redirect/dummy_models_controller.rb +1 -1
  36. data/spec/dummy/app/controllers/block_show/dummy_models_controller.rb +1 -1
  37. data/spec/dummy/app/controllers/built/dummy_models_controller.rb +0 -5
  38. data/spec/dummy/app/controllers/dummy_models_controller.rb +0 -5
  39. data/spec/dummy/app/controllers/finder/dummy_models_controller.rb +0 -5
  40. data/spec/dummy/app/controllers/html_modes/base_controller.rb +0 -5
  41. data/spec/dummy/app/controllers/invalid_status/dummy_models_controller.rb +1 -1
  42. data/spec/dummy/app/controllers/nested/dummy_models_controller.rb +0 -5
  43. data/spec/dummy/app/controllers/nested_route/dummy_models_controller.rb +0 -5
  44. data/spec/dummy/app/controllers/redirect_auth/dummy_models_controller.rb +0 -5
  45. data/spec/dummy/app/controllers/scoped/dummy_models_controller.rb +0 -5
  46. data/spec/dummy/app/controllers/scoped_params/dummy_models_controller.rb +0 -5
  47. data/spec/dummy/app/controllers/strict/dummy_models_controller.rb +0 -5
  48. data/spec/dummy/app/controllers/unpaginated_scoped/dummy_models_controller.rb +0 -5
  49. data/spec/dummy/app/controllers/without_pagination/dummy_models_controller.rb +0 -5
  50. data/spec/simple_crud/rspec_config_spec.rb +6 -0
  51. data/spec/simple_crud_controller_spec.rb +38 -0
  52. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e280efd8ead44768d16e0ba663e25a40d6972b53e253281d1c7eac0735421b64
4
- data.tar.gz: 78625a2a759ca5fda1e7d41e421db92ed721f2e2c343524f0580cd810d32ac7a
3
+ metadata.gz: dbcb6881c359fa3b5c4ce518871a4f378d92e0698ab7d57dc489315f2f25b80b
4
+ data.tar.gz: 62cf8cbd6df845cd23a388e9b2a1f8ebfdae784ff91f4e57268688bce0c0bf87
5
5
  SHA512:
6
- metadata.gz: 406a83cc98deaa7fa3ba5f7ccb9a12486a903b6aef81bddd0a5f4f9c595ffa64e7414cb8a718d4a4fe96f987fcefaf34a8b201cbe16aab4db2721eea0bd19397
7
- data.tar.gz: 7177530ba1a01fcf526c406a14f3bf64bfcf895ce5675f4acca5f24f28c57db90859ddab43866d314f70e723cfebda24bc5930d64ac66a01d29bc6246792c04a
6
+ metadata.gz: 4406326eab40876599274e927df02c9c3470d3f753dcd5f0f150b67a7b3087e2a965ec0fd18ad1e007bada514954f9a665d573d18da98bf7c93aee3ffebc1637
7
+ data.tar.gz: 1deddc698fb6008531d59e5656675086a309dbc26177b403c023e7743463425626b8e977785f6ef2cbe122d4f251ad697944d1c71f665e498666feecedbae792
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  ## Change log
2
2
 
3
+ ### V0.4.0
4
+
5
+ Breaking:
6
+ * Blocks given to `simple_crud_for` no longer imply `html: true`. HTML controllers with render blocks must pass `html: true` explicitly.
7
+
8
+ New options:
9
+ * `authenticate_headers:` controls whether shared examples set auth headers and run the unauthorized test, independent of `authenticate:`. Defaults to `authenticate:`. Set `authenticate: false, authenticate_headers: true` when a base-controller `before_action` handles auth so the lambda skips the call but tests still cover the auth path.
10
+ * `simple_crud_defaults(options)` sets option defaults at the controller level. Subclasses inherit. Per-action options override. Precedence: gem defaults < controller defaults < per-action options.
11
+
12
+ Fixes:
13
+ * Use `RSpec.shared_examples` instead of the top-level alias, which is unavailable with `config.disable_monkey_patching!`.
14
+ * Auto-require `SimpleCrud::Authorization::Adapter` on `require 'simple_crud'`.
15
+ * Remove `cattr_accessor :params, :permitted` (thread-unsafe, never read by the gem). Remove the `set_params` boilerplate from host controllers.
16
+ * Raise a clear error when `owner_association` names an attribute the model doesn't have, instead of a bare `NoMethodError` from FactoryBot.
17
+
3
18
  ### V0.3.1
4
19
 
5
20
  Shared examples configuration:
data/README.md CHANGED
@@ -18,6 +18,7 @@ SimpleCrud
18
18
  - [Serializer](#serializer)
19
19
  - [HTML](#html)
20
20
  - [Finder](#finder)
21
+ - [Controller-level defaults](#controller-level-defaults)
21
22
  - [Shared examples](#shared-examples)
22
23
  - [Contributing](#contributing)
23
24
  - [Releases](#releases)
@@ -68,12 +69,6 @@ Before SimpleCrud can be used, some boilerplate is needed. Add the following to
68
69
  include Pundit::Authorization
69
70
  include Wor::Paginate
70
71
  extend SimpleCrudController
71
-
72
- before_action :set_params
73
-
74
- def set_params
75
- SimpleCrudController.params = params
76
- end
77
72
  ```
78
73
 
79
74
  (Skip `include Pundit::Authorization` / `include Wor::Paginate` if you're using a different adapter, or `authorize: false` / `paginate: false` everywhere.)
@@ -105,7 +100,8 @@ simple_crud_for :index, paginate: false, authorize: false, serializer: CustomSer
105
100
 
106
101
  - Paginate: whether it should paginate or not. `true` paginates via the configured pagination adapter (wor-paginate by default), `false` doesn't paginate
107
102
  - Authorize: whether it should check authorization via the configured authorization adapter (Pundit by default)
108
- - Authenticate: whether it should use Devise to check for a current_user
103
+ - Authenticate: whether the generated action calls `authenticate_user!`. `true` (default) or `false`
104
+ - Authenticate_headers: whether shared examples set auth headers and run the unauthorized test. Defaults to `authenticate:`. Set independently when a base-controller `before_action` handles auth and the lambda should skip `authenticate_user!`
109
105
  - Serializer: specify a particular serializer you should use
110
106
  - Html: renders the action's ERB template instead of JSON (valid for `:index`, `:show`, `:new`, `:edit`, `:create`, `:update` and `:destroy`). Only meaningful in controllers that render templates
111
107
  - Scope: only valid for `:index`. A `Proc`/`lambda` taking `current_user` (plus the controller's `params` if it takes a second argument) that returns the relation to list, overriding the default `policy_scope`. The user is resolved via `SimpleCrud::Config.user_method` (`:current_user` by default; set it to e.g. `:current_admin`)
@@ -114,6 +110,22 @@ simple_crud_for :index, paginate: false, authorize: false, serializer: CustomSer
114
110
  - Raise_on_invalid: only valid for `:create` and `:update`. Keeps the strict `create!`/`update!` semantics (raising on invalid input) instead of returning `422` with the validation errors
115
111
  - Redirect: only valid for HTML-mode `:create`, `:update` and `:destroy`. A `Proc`/`lambda` (called with the record) or a literal path used as the success redirect target. Defaults to the record (`:create`/`:update`) or the model's collection path (`:destroy`)
116
112
 
113
+ #### Controller-level defaults
114
+
115
+ `simple_crud_defaults` sets option defaults for every `simple_crud_for` in the controller. Subclasses inherit; per-action options override.
116
+
117
+ ```ruby
118
+ class Api::BaseController < ActionController::API
119
+ extend SimpleCrudController
120
+ simple_crud_defaults authorize: false, authenticate: false, authenticate_headers: true
121
+ end
122
+
123
+ class Api::PostsController < Api::BaseController
124
+ simple_crud_for :show # inherits defaults
125
+ simple_crud_for :create, authorize: true # overrides for this action only
126
+ end
127
+ ```
128
+
117
129
  You'll need a few things so they work correctly:
118
130
 
119
131
  ### Options
@@ -247,7 +259,13 @@ end
247
259
  ```
248
260
 
249
261
  #### Authenticate
250
- SimpleCrud will assume a current_user method. Future versions will support a custom model. Defining a current_user method in ApplicationController should work if you're using a different model, as of now.
262
+ `authenticate: true` (default) calls `authenticate_user!` inside the generated action. `authenticate: false` skips it.
263
+
264
+ If your base controller already runs `before_action :authenticate_user!`, set `authenticate: false` to avoid a double call and `authenticate_headers: true` so shared examples still cover the auth path:
265
+
266
+ ```ruby
267
+ simple_crud_defaults authenticate: false, authenticate_headers: true
268
+ ```
251
269
 
252
270
  #### Serializer
253
271
  The name of the serializer, by default, is the name of the model followed by Serializer, as is the standard for [ActiveModelSerializers](https://github.com/rails-api/active_model_serializers). It's possible to just pass a custom serializer class though. As for the serializer itself, it's a standard serializer, with the gotcha that you need to include `:id` for the SimpleCrud examples to work.
@@ -279,16 +297,22 @@ simple_crud_for :update, html: true
279
297
  simple_crud_for :destroy, html: true
280
298
  ```
281
299
 
282
- Or pass a block that renders explicitly, overriding the auto-render. The block receives the records for `:index`, the record for `:show`/`:new`, or the record plus a saved flag for `:create`/`:update`/`:destroy`. Passing a block also implies `html: true` for the shared examples (so a server-rendered block is asserted as HTML); if your block renders JSON instead, pass `html: false` explicitly:
300
+ Or pass a block that renders explicitly, overriding the auto-render. The block receives the records for `:index`, the record for `:show`/`:new`, or the record plus a saved flag for `:create`/`:update`/`:destroy`. Blocks do not change the `html:` default; pass it explicitly so the shared examples know which request format to use:
283
301
 
284
302
  ```ruby
285
- simple_crud_for :index do |records|
303
+ # Server-rendered block: pass html: true so shared examples send HTML requests
304
+ simple_crud_for :index, html: true do |records|
286
305
  render :index, locals: { models: records }
287
306
  end
288
307
 
289
- simple_crud_for :create do |record, saved|
308
+ simple_crud_for :create, html: true do |record, saved|
290
309
  saved ? redirect_to(record) : render(:new, locals: { model: record })
291
310
  end
311
+
312
+ # API block: html: false is the default
313
+ simple_crud_for :show, html: false do |record|
314
+ render json: record.as_json(only: %i[id name])
315
+ end
292
316
  ```
293
317
 
294
318
  #### Build
@@ -320,7 +344,7 @@ simple_crud_for :destroy, finder: ->(params) { current_user.models.find(params[:
320
344
  When omitted it defaults to `klass.find(params[:id])`, and `not_found` is still returned whenever the finder finds no record.
321
345
 
322
346
  ### Shared examples
323
- While optional, using the included shared examples saves you from writing the standard test cases for the methods. You can even use them if you didn't use `simple_crud_for`, as a set of basic tests. To include them, just add `require 'simple_crud/rspec'` to your `rails_helper.rb` file and add the lines you need to your `*_spec.rb` files:
347
+ While optional, using the included shared examples saves you from writing the standard test cases for the methods. You can even use them if you didn't use `simple_crud_for`, as a set of basic tests. To include them, add `require 'simple_crud/rspec'` to your `rails_helper.rb` **after** `require "rspec/rails"`, then add the lines you need to your `*_spec.rb` files:
324
348
  ```ruby
325
349
  require 'rails_helper'
326
350
 
@@ -10,9 +10,14 @@ module SimpleCrud
10
10
  described_class.instance_variable_get(:@simple_crud_metadata)[method][option]
11
11
  end
12
12
 
13
- %i[paginate authorize authenticate serializer html finder scope build raise_on_invalid block].each do |option|
13
+ %i[paginate authorize authenticate serializer html finder scope build raise_on_invalid block
14
+ authenticate_headers].each do |option|
14
15
  define_method("check_#{option}") { |method| get_option(method, option) }
15
16
  end
17
+
18
+ def check_authenticate(method)
19
+ check_authenticate_headers(method)
20
+ end
16
21
  end
17
22
  end
18
23
  end
@@ -15,7 +15,22 @@ module SimpleCrud
15
15
  end
16
16
 
17
17
  def model
18
- @model ||= create_record(model_class, model_attributes)
18
+ @model ||= begin
19
+ validate_owner_association!
20
+ create_record(model_class, model_attributes)
21
+ end
22
+ end
23
+
24
+ def validate_owner_association!
25
+ assoc = owner_association
26
+ return unless assoc
27
+
28
+ klass = model_class_object
29
+ return if klass.method_defined?("#{assoc}=") || klass.column_names.include?(assoc.to_s)
30
+
31
+ raise "simple_crud: owner_association is :#{assoc} but #{klass} has no #{assoc}= setter. " \
32
+ 'Set `simple_crud: { owner_association: nil }` in your describe block or ' \
33
+ 'override model_attributes directly.'
19
34
  end
20
35
 
21
36
  def model_attributes
@@ -11,12 +11,12 @@ module SimpleCrudController
11
11
  # Include, not extend: controllers gain these by extending SimpleCrudController.
12
12
  include SimpleCrud::ActionLambdas
13
13
 
14
- cattr_accessor :params, :permitted
15
-
16
14
  # Possible options:
17
15
  ### authorize: check authorization via Config.authorization_adapter (Pundit by default)
18
16
  ### paginate: paginate the list via Config.pagination_adapter (wor-paginate by default)
19
- ### authenticate: use devise to authenticate
17
+ ### authenticate: true calls authenticate_user! inside the action lambda; false skips it
18
+ ### authenticate_headers: whether shared examples set auth headers and run the unauthorized
19
+ ### test (defaults to authenticate:); set independently when a base-controller before_action handles auth
20
20
  ### serializer: use a particular serializer (both each_serializer and serializer)
21
21
  ### html: render the action's ERB template instead of JSON (index/show/new/edit/create/update/destroy)
22
22
  ### finder: custom record lookup (Proc/lambda or Symbol) for :show/:update/:destroy/:edit
@@ -26,7 +26,6 @@ module SimpleCrudController
26
26
  ### A block given to simple_crud_for renders explicitly: it receives the records for :index,
27
27
  ### the record for :show/:new/:edit, or the record and a saved flag for :create/:update/:destroy
28
28
  def simple_crud_for(method, parameters = {}, &block)
29
- parameters[:html] = true if block && !parameters.key?(:html)
30
29
  parameters[:block] = true if block
31
30
  parameters = parameters_with_defaults(parameters)
32
31
  klass = simple_crud_controller_model
@@ -37,12 +36,28 @@ module SimpleCrudController
37
36
  write_metadata(method, parameters)
38
37
  end
39
38
 
39
+ def simple_crud_defaults(options = {})
40
+ @simple_crud_defaults = simple_crud_inherited_defaults.merge(options)
41
+ end
42
+
43
+ def simple_crud_inherited_defaults
44
+ ancestors.each do |ancestor|
45
+ next unless ancestor.instance_variable_defined?(:@simple_crud_defaults)
46
+
47
+ return ancestor.instance_variable_get(:@simple_crud_defaults)
48
+ end
49
+ {}
50
+ end
51
+
40
52
  def parameters_with_defaults(parameters)
41
53
  defaults = {
42
- authorize: true, paginate: true, authenticate: true, serializer: nil,
43
- html: false, finder: nil, scope: nil, build: nil, raise_on_invalid: false
54
+ authorize: true, paginate: true, authenticate: true, authenticate_headers: nil,
55
+ serializer: nil, html: false, finder: nil, scope: nil, build: nil, raise_on_invalid: false
44
56
  }
45
- defaults.each { |key, value| parameters[key] = value unless parameters.key?(key) }
57
+ defaults.merge(simple_crud_inherited_defaults).each do |key, value|
58
+ parameters[key] = value unless parameters.key?(key)
59
+ end
60
+ parameters[:authenticate_headers] = parameters[:authenticate] if parameters[:authenticate_headers].nil?
46
61
  parameters
47
62
  end
48
63
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleCrud
4
- VERSION = '0.3.1'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/simple_crud.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'simple_crud/version'
4
4
  require_relative 'simple_crud/config'
5
+ require_relative 'simple_crud/authorization/adapter'
5
6
  require_relative 'simple_crud/simple_crud_controller'
6
7
 
7
8
  # Simplified CRUD endpoints for Rails API controllers.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'authorization adapter #authorize' do |record_class, denied_error|
3
+ RSpec.shared_examples 'authorization adapter #authorize' do |record_class, denied_error|
4
4
  it 'passes for a record the adapter allows' do
5
5
  expect { adapter.authorize(controller, record_class.new(1)) }.not_to raise_error
6
6
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for create' do
3
+ RSpec.shared_examples 'simple crud for create' do
4
4
  describe 'POST #create' do
5
5
  context 'without authenticated user' do
6
6
  subject!(:req) do
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for create with block' do
3
+ RSpec.shared_examples 'simple crud for create with block' do
4
4
  describe 'POST #create with a render block' do
5
5
  context 'when successfully creating a record' do
6
6
  include_context 'with authenticated user' if check_authenticate(:create)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for create with build' do
3
+ RSpec.shared_examples 'simple crud for create with build' do
4
4
  describe 'POST #create with a build hook' do
5
5
  include_context 'with authenticated user' if check_authenticate(:create)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for destroy' do
3
+ RSpec.shared_examples 'simple crud for destroy' do
4
4
  describe 'DELETE #destroy' do
5
5
  context 'without authenticated user' do
6
6
  subject!(:req) do
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for destroy with block' do
3
+ RSpec.shared_examples 'simple crud for destroy with block' do
4
4
  describe 'DELETE #destroy with a render block' do
5
5
  include_context 'with authenticated user' if check_authenticate(:destroy)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for destroy with finder' do
3
+ RSpec.shared_examples 'simple crud for destroy with finder' do
4
4
  describe 'DELETE #destroy with a custom finder' do
5
5
  include_context 'with authenticated user' if check_authenticate(:destroy)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for edit' do
3
+ RSpec.shared_examples 'simple crud for edit' do
4
4
  describe 'GET #edit' do
5
5
  subject(:edit_request) { get :edit, params: with_route_params(edit_params), format: request_format(:edit) }
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for index' do
3
+ RSpec.shared_examples 'simple crud for index' do
4
4
  describe 'GET #index' do
5
5
  let(:created_models) { create_records(model_class, 10, model_attributes) }
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for index with block' do
3
+ RSpec.shared_examples 'simple crud for index with block' do
4
4
  describe 'GET #index with a render block' do
5
5
  let(:created_models) { create_records(model_class, 2, model_attributes) }
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for index with scope' do
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
6
  let(:other_models) { create_records(model_class, 3, other_scoped_attributes) }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for new' do
3
+ RSpec.shared_examples 'simple crud for new' do
4
4
  describe 'GET #new' do
5
5
  include_examples 'simple crud without authenticated user', :new
6
6
  include_examples 'simple crud when not authorized', :new, :get
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for new with block' do
3
+ RSpec.shared_examples 'simple crud for new with block' do
4
4
  describe 'GET #new with a render block' do
5
5
  include_context 'with authenticated user' if check_authenticate(:new)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for new with build' do
3
+ RSpec.shared_examples 'simple crud for new with build' do
4
4
  describe 'GET #new with a build hook' do
5
5
  include_context 'with authenticated user' if check_authenticate(:new)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for show' do
3
+ RSpec.shared_examples 'simple crud for show' do
4
4
  describe 'GET #show' do
5
5
  subject(:show_request) { get :show, params: with_route_params(show_params), format: request_format(:show) }
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for show with block' do
3
+ RSpec.shared_examples 'simple crud for show with block' do
4
4
  describe 'GET #show with a render block' do
5
5
  include_context 'with authenticated user' if check_authenticate(:show)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for show with finder' do
3
+ RSpec.shared_examples 'simple crud for show with finder' do
4
4
  describe 'GET #show with a custom finder' do
5
5
  include_context 'with authenticated user' if check_authenticate(:show)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for update' do
3
+ RSpec.shared_examples 'simple crud for update' do
4
4
  describe 'PUT #update' do
5
5
  context 'without authenticated user' do
6
6
  subject!(:req) do
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud for update with finder' do
3
+ RSpec.shared_examples 'simple crud for update with finder' do
4
4
  describe 'PUT #update with a custom finder' do
5
5
  include_context 'with authenticated user' if check_authenticate(:update)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud not found with finder' do |http_method, action|
3
+ RSpec.shared_examples 'simple crud not found with finder' do |http_method, action|
4
4
  context 'when the model does not exist' do
5
5
  before do
6
6
  send(http_method, action, params: with_route_params(finder_key => "nonexistent-#{finder_key}"),
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud renders template' do |template, status = :ok|
3
+ RSpec.shared_examples 'simple crud renders template' do |template, status = :ok|
4
4
  it "renders the #{template} template", :aggregate_failures do
5
5
  expect(response).to have_http_status(resolve(status))
6
6
  expect(response).to render_template(template) if assert_html_template
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud when not authorized' do |action, verb, request_params = {}|
3
+ RSpec.shared_examples 'simple crud when not authorized' do |action, verb, request_params = {}|
4
4
  if check_authorize(action)
5
5
  context 'when not authorized' do
6
6
  include_context 'with authenticated user' if check_authenticate(action)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'simple crud without authenticated user' do |action|
3
+ RSpec.shared_examples 'simple crud without authenticated user' do |action|
4
4
  context 'without authenticated user' do
5
5
  subject!(:req) { get action, params: with_route_params({}) }
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- shared_examples 'unauthorized when not logged in' do
3
+ RSpec.shared_examples 'unauthorized when not logged in' do
4
4
  context 'when the user is not logged in' do
5
5
  it 'returns the unauthenticated status' do
6
6
  req
@@ -5,12 +5,7 @@ module Block
5
5
  include Wor::Paginate
6
6
  extend SimpleCrudController
7
7
 
8
- before_action :set_params
9
- def set_params
10
- SimpleCrudController.params = params
11
- end
12
-
13
- simple_crud_for :index, paginate: false, authenticate: false, authorize: false do |records|
8
+ simple_crud_for :index, html: true, paginate: false, authenticate: false, authorize: false do |records|
14
9
  render :index, locals: { models: records }
15
10
  end
16
11
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module BlockNew
4
4
  class DummyModelsController < BlockModes::BaseController
5
- simple_crud_for :new, authenticate: false, authorize: false do |record|
5
+ simple_crud_for :new, html: true, authenticate: false, authorize: false do |record|
6
6
  render_model(record, :new)
7
7
  end
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module BlockRedirect
4
4
  class DummyModelsController < HtmlModes::BaseController
5
- simple_crud_for :destroy, authenticate: false, authorize: false do |_record, destroyed|
5
+ simple_crud_for :destroy, html: true, authenticate: false, authorize: false do |_record, destroyed|
6
6
  if destroyed
7
7
  redirect_to action: :show, notice: 'removed'
8
8
  else
@@ -2,7 +2,7 @@
2
2
 
3
3
  module BlockShow
4
4
  class DummyModelsController < BlockModes::BaseController
5
- simple_crud_for :show, authenticate: false, authorize: false do |record|
5
+ simple_crud_for :show, html: true, authenticate: false, authorize: false do |record|
6
6
  render_model(record, :show)
7
7
  end
8
8
  end
@@ -6,11 +6,6 @@ module Built
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  def dummy_model_params
15
10
  params.permit(:name, :something, :user_id, :slug)
16
11
  end
@@ -6,11 +6,6 @@ class DummyModelsController < ApplicationController
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  def dummy_model_params
15
10
  params.permit(:name, :something, :user_id, :slug)
16
11
  end
@@ -6,11 +6,6 @@ module Finder
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  def dummy_model_params
15
10
  params.permit(:name, :something, :user_id)
16
11
  end
@@ -5,11 +5,6 @@ module HtmlModes
5
5
  include Wor::Paginate
6
6
  extend SimpleCrudController
7
7
 
8
- before_action :set_params
9
- def set_params
10
- SimpleCrudController.params = params
11
- end
12
-
13
8
  def dummy_model_params
14
9
  params.permit(:name, :something, :user_id, :slug)
15
10
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module InvalidStatus
4
4
  class DummyModelsController < HtmlModes::BaseController
5
- simple_crud_for :create, authenticate: false, authorize: false do |record, saved|
5
+ simple_crud_for :create, html: true, authenticate: false, authorize: false do |record, saved|
6
6
  if saved
7
7
  redirect_to(record)
8
8
  else
@@ -6,11 +6,6 @@ module Nested
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  def dummy_model_params
15
10
  params.require(:dummy_model).permit(:name, :something, :user_id, :slug)
16
11
  end
@@ -6,11 +6,6 @@ module NestedRoute
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  def dummy_model_params
15
10
  params.require(:dummy_model).permit(:name, :something, :user_id, :slug, :classroom_slug)
16
11
  end
@@ -10,11 +10,6 @@ module RedirectAuth
10
10
 
11
11
  rescue_from UnauthenticatedError, with: :redirect_to_login
12
12
 
13
- before_action :set_params
14
- def set_params
15
- SimpleCrudController.params = params
16
- end
17
-
18
13
  def authenticate_user!
19
14
  raise UnauthenticatedError unless current_user
20
15
  end
@@ -6,11 +6,6 @@ module Scoped
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  simple_crud_for :index, scope: ->(user) { DummyModel.where(user: user) }
15
10
  end
16
11
  end
@@ -6,11 +6,6 @@ module ScopedParams
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  simple_crud_for :index, scope: ->(user, params) { DummyModel.where(user: user, something: params[:something]) }
15
10
  end
16
11
  end
@@ -6,11 +6,6 @@ module Strict
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  def dummy_model_params
15
10
  params.permit(:name, :something, :user_id, :slug)
16
11
  end
@@ -6,11 +6,6 @@ module UnpaginatedScoped
6
6
  include Pundit::Authorization
7
7
  extend SimpleCrudController
8
8
 
9
- before_action :set_params
10
- def set_params
11
- SimpleCrudController.params = params
12
- end
13
-
14
9
  simple_crud_for :index, paginate: false, scope: ->(user) { DummyModel.where(user: user) }
15
10
  end
16
11
  end
@@ -5,11 +5,6 @@ module WithoutPagination
5
5
  include Pundit::Authorization
6
6
  extend SimpleCrudController
7
7
 
8
- before_action :set_params
9
- def set_params
10
- SimpleCrudController.params = params
11
- end
12
-
13
8
  simple_crud_for :index, paginate: false
14
9
  end
15
10
  end
@@ -82,6 +82,12 @@ describe SimpleCrud::RSpec do
82
82
  expect(model_attributes).to eq(user: current_user)
83
83
  end
84
84
 
85
+ it 'raises a clear error when owner_association has no setter on the model' do
86
+ klass = Class.new { def self.column_names = [] }
87
+ allow(self).to receive_messages(owner_association: :nonexistent, model_class_object: klass)
88
+ expect { validate_owner_association! }.to raise_error(/owner_association is :nonexistent/)
89
+ end
90
+
85
91
  describe 'with simple_crud metadata',
86
92
  simple_crud: { finder_key: :token, model_attributes: -> { { overridden: true } } } do
87
93
  it 'prefers metadata for overridden settings' do
@@ -8,6 +8,14 @@ class UnpoliceableThingsController
8
8
  extend SimpleCrudController
9
9
  end
10
10
 
11
+ class BaseWithDefaultsController
12
+ extend SimpleCrudController
13
+ simple_crud_defaults authorize: false, authenticate: false, authenticate_headers: true
14
+ end
15
+
16
+ class InheritingController < BaseWithDefaultsController
17
+ end
18
+
11
19
  describe SimpleCrudController do
12
20
  describe '.check_policies' do
13
21
  it 'returns when a matching policy exists' do
@@ -21,6 +29,36 @@ describe SimpleCrudController do
21
29
  end
22
30
  end
23
31
 
32
+ describe '.simple_crud_defaults' do
33
+ it 'applies to parameters_with_defaults', :aggregate_failures do
34
+ params = BaseWithDefaultsController.parameters_with_defaults({})
35
+ expect(params[:authorize]).to be false
36
+ expect(params[:authenticate]).to be false
37
+ expect(params[:authenticate_headers]).to be true
38
+ end
39
+
40
+ it 'are inherited by subclasses', :aggregate_failures do
41
+ params = InheritingController.parameters_with_defaults({})
42
+ expect(params[:authorize]).to be false
43
+ expect(params[:authenticate]).to be false
44
+ expect(params[:authenticate_headers]).to be true
45
+ end
46
+
47
+ it 'can be overridden per action', :aggregate_failures do
48
+ params = InheritingController.parameters_with_defaults(authorize: true)
49
+ expect(params[:authorize]).to be true
50
+ expect(params[:authenticate]).to be false
51
+ expect(params[:authenticate_headers]).to be true
52
+ end
53
+
54
+ it 'does not affect unrelated controllers', :aggregate_failures do
55
+ params = DummyModelsController.parameters_with_defaults({})
56
+ expect(params[:authorize]).to be true
57
+ expect(params[:authenticate]).to be true
58
+ expect(params[:authenticate_headers]).to be true
59
+ end
60
+ end
61
+
24
62
  describe '.check_serializer' do
25
63
  it 'returns when the serializer option is blank' do
26
64
  expect { DummyModelsController.check_serializer({}) }.not_to raise_error
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wor-simple_crud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - icoluccio
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-08-22 00:00:00.000000000 Z
10
+ date: 2026-08-30 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails