crudable-rails 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +166 -8
- data/lib/crudable/rails/base.rb +60 -16
- data/lib/crudable/rails/engine.rb +4 -0
- data/lib/crudable/rails/nestable.rb +1 -1
- data/lib/crudable/rails/version.rb +1 -1
- data/lib/crudable-rails.rb +5 -1
- metadata +54 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8978c74f649c14c989bad8ae160fb16544cbfbff0711d7322316aec666effa08
|
4
|
+
data.tar.gz: '04709d211dabd30b4daac9d5bc5b7249eff31d6eb0c5715b03ce623bd6a898b8'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80c559e8bea6582bde9b75ea524311d6a1e45f89bf0e24584b260c2ef8b8636998d17fd4dbc030b405a199fcc2317ecac464e9ddef565edf1475c3fbbbb0429f
|
7
|
+
data.tar.gz: 28f94c76baa49ea628e281e8b83d29f23c148c956ee1d691419540db5bbee886d416d27a69ee6823f57541d637490db2bec1306ab5ba9280c91e22785dcad7a0
|
data/README.md
CHANGED
@@ -1,28 +1,186 @@
|
|
1
|
-
# Crudable
|
2
|
-
Short description and motivation.
|
1
|
+
# Crudable Rails
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
`crudable-rails` is a Ruby on Rails gem that provides a set of helpers and modules to simplify the implementation of CRUD operations in Rails controllers.
|
4
|
+
|
5
|
+
It uses the following gems to enhance the functionality:
|
6
|
+
|
7
|
+
- `Pundit` for authorization
|
8
|
+
- `Kaminari` for pagination
|
9
|
+
- `FriendlyId` for friendly finders
|
10
|
+
- `HasScope` for filtering
|
11
|
+
- `Discard` for soft deletion
|
6
12
|
|
7
13
|
## Installation
|
14
|
+
|
8
15
|
Add this line to your application's Gemfile:
|
9
16
|
|
10
17
|
```ruby
|
11
|
-
gem "crudable"
|
18
|
+
gem "crudable-rails"
|
12
19
|
```
|
13
20
|
|
14
21
|
And then execute:
|
22
|
+
|
15
23
|
```bash
|
16
|
-
$ bundle
|
24
|
+
$ bundle install
|
17
25
|
```
|
18
26
|
|
19
27
|
Or install it yourself as:
|
28
|
+
|
20
29
|
```bash
|
21
|
-
$ gem install crudable
|
30
|
+
$ gem install crudable-rails
|
31
|
+
```
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
### Controller Setup
|
36
|
+
|
37
|
+
To use crudable-rails in your controllers, call the `crudable` method. You can also specify if the controller is nested by passing the `nested: true` option.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
class ProductsController < ApplicationController
|
41
|
+
crudable
|
42
|
+
end
|
43
|
+
|
44
|
+
class ProductSizesController < ApplicationController
|
45
|
+
crudable nested: true
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
## Customizing CRUD Actions
|
50
|
+
|
51
|
+
You can override the default behavior of CRUD actions by defining the following methods in your controller:
|
52
|
+
|
53
|
+
- `before_authorize_create`
|
54
|
+
- `after_authorize_create`
|
55
|
+
- `on_successful_create`
|
56
|
+
- `on_successful_create_render`
|
57
|
+
- `on_failed_create_setup`
|
58
|
+
- `on_failed_create_render`
|
59
|
+
- `before_authorize_update`
|
60
|
+
- `after_authorize_update`
|
61
|
+
- `on_successful_update`
|
62
|
+
- `on_successful_update_render`
|
63
|
+
- `on_failed_update_setup`
|
64
|
+
- `on_failed_update_render`
|
65
|
+
- `on_successful_destroy_render`
|
66
|
+
- `on_failed_destroy_render`
|
67
|
+
|
68
|
+
For example:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
class ProductsController < ApplicationController
|
72
|
+
include Crudable::Rails::Controller
|
73
|
+
|
74
|
+
crudable
|
75
|
+
|
76
|
+
def on_successful_create
|
77
|
+
# Custom behavior on successful create
|
78
|
+
end
|
79
|
+
|
80
|
+
def on_failed_create_render
|
81
|
+
respond_to do |format|
|
82
|
+
format.html { render :new, status: :unprocessable_entity }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
By default, Turbo Streams are supported for create, update, and destroy actions. If Turbo Streams are not available, the gem will fallback to rendering HTML responses. If you require support for other formats, you can override the default behavior by defining the appropriate methods in your controller.
|
89
|
+
|
90
|
+
### Required Private Methods
|
91
|
+
|
92
|
+
### `permitted_params`
|
93
|
+
|
94
|
+
This method should return the permitted parameters for the resource as an array. It's required to be defined on all controllers.
|
95
|
+
|
96
|
+
### Optional Private Methods
|
97
|
+
|
98
|
+
The following private methods are available for use in your controllers:
|
99
|
+
|
100
|
+
### `after_create_redirect_path`
|
101
|
+
|
102
|
+
This method should return the path to redirect to after a successful create. By default this will redirect to the namespaced index of the resource being created.
|
103
|
+
|
104
|
+
### `after_create_notice`
|
105
|
+
|
106
|
+
This method should return the notice to display after a successful create. By default this will return a success message via i18n.
|
107
|
+
|
108
|
+
### `after_update_redirect_path`
|
109
|
+
|
110
|
+
This method should return the path to redirect to after a successful update. By default this will redirect to the namespaced show path of the resource being updated.
|
111
|
+
|
112
|
+
### `after_update_notice`
|
113
|
+
|
114
|
+
This method should return the notice to display after a successful update. By default this will return a success message via i18n.
|
115
|
+
|
116
|
+
### `after_destroy_redirect_path`
|
117
|
+
|
118
|
+
This method should return the path to redirect to after a successful destroy. By default this will redirect to the namespaced index of the resource being destroyed.
|
119
|
+
|
120
|
+
### `after_failed_destroy_redirect_path`
|
121
|
+
|
122
|
+
This method should return the path to redirect to after a failed destroy. Default: `after_destroy_redirect_path`.
|
123
|
+
|
124
|
+
### `after_destroy_notice`
|
125
|
+
|
126
|
+
This method should return the notice to display after a successful destroy. By default this will return a success message via i18n.
|
127
|
+
|
128
|
+
### `after_failed_destroy_alert`
|
129
|
+
|
130
|
+
This method should return the alert to display after a failed destroy. By default this will return an error message via i18n.
|
131
|
+
|
132
|
+
### `discard?`
|
133
|
+
|
134
|
+
This method should return a boolean value to determine if the resource should be discarded. If it returns `false` the resource will be destroyed. Default: `false`.
|
135
|
+
|
136
|
+
### `singleton?`
|
137
|
+
|
138
|
+
This method should return a boolean value to determine if the resource is a singleton. Default: `false`.
|
139
|
+
|
140
|
+
### `finder_param`
|
141
|
+
|
142
|
+
This method should return the parameter used to find the resource. Default: `:id`.
|
143
|
+
|
144
|
+
### `paginate_resource?`
|
145
|
+
|
146
|
+
This method should return a boolean value to determine if the resource should be paginated. Default: `true` if Kaminari is available, otherwise `false`.
|
147
|
+
|
148
|
+
### `friendly_finders?`
|
149
|
+
|
150
|
+
This method should return a boolean value to determine if the resource should be found using friendly finders. Default: `true` if FriendlyId is available, otherwise `false`.
|
151
|
+
|
152
|
+
### `skip_initialize_create?`
|
153
|
+
|
154
|
+
This method should return a boolean value to determine if the resource should be initialized on create. Default: `false`.
|
155
|
+
|
156
|
+
### `(create|update)_params`
|
157
|
+
|
158
|
+
These methods should return the permitted parameters for the resource as an array. They are optional and can be defined if create and update methods need different parameters allowed.
|
159
|
+
|
160
|
+
## Overriding `authorizable_resource` with a Namespace
|
161
|
+
|
162
|
+
The `authorizable_resource` method can be overridden to customize the resource authorization logic, especially when dealing with namespaced resources. This method should return the resource that needs to be authorized.
|
163
|
+
|
164
|
+
For example, if you have a namespaced controller:
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
module Admin
|
168
|
+
class ProductsController < ApplicationController
|
169
|
+
crudable
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def authorizable_resource
|
174
|
+
[:admin, @product]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
22
178
|
```
|
23
179
|
|
24
180
|
## Contributing
|
25
|
-
|
181
|
+
|
182
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/your-username/crudable-rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
|
26
183
|
|
27
184
|
## License
|
185
|
+
|
28
186
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/crudable/rails/base.rb
CHANGED
@@ -27,9 +27,11 @@ module Crudable
|
|
27
27
|
|
28
28
|
def create # rubocop:disable Metrics/MethodLength
|
29
29
|
instance_variable_set("@#{resource_var_name}", resource_class.new(create_params)) unless skip_initialize_create?
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
if defined?(Pundit)
|
31
|
+
before_authorize_create
|
32
|
+
authorize_resource
|
33
|
+
after_authorize_create
|
34
|
+
end
|
33
35
|
if instance_variable_get("@#{resource_var_name}").save
|
34
36
|
on_successful_create
|
35
37
|
on_successful_create_render
|
@@ -42,9 +44,11 @@ module Crudable
|
|
42
44
|
def edit; end
|
43
45
|
|
44
46
|
def update
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
if defined?(Pundit)
|
48
|
+
before_authorize_update
|
49
|
+
authorize_resource
|
50
|
+
after_authorize_update
|
51
|
+
end
|
48
52
|
if instance_variable_get("@#{resource_var_name}").update update_params
|
49
53
|
on_successful_update
|
50
54
|
on_successful_update_render
|
@@ -55,10 +59,12 @@ module Crudable
|
|
55
59
|
end
|
56
60
|
|
57
61
|
def destroy
|
58
|
-
authorize_resource(destroy_method)
|
62
|
+
authorize_resource(destroy_method) if defined?(Pundit)
|
59
63
|
if instance_variable_get("@#{resource_var_name}").send(destroy_method)
|
64
|
+
on_successful_destroy
|
60
65
|
on_successful_destroy_render
|
61
66
|
else
|
67
|
+
on_failed_destroy
|
62
68
|
on_failed_destroy_render
|
63
69
|
end
|
64
70
|
end
|
@@ -114,7 +120,7 @@ module Crudable
|
|
114
120
|
end
|
115
121
|
|
116
122
|
def friendly_finders?
|
117
|
-
return false unless defined?(FriendlyId) &&
|
123
|
+
return false unless defined?(FriendlyId) && resource_class.respond_to?(:friendly)
|
118
124
|
|
119
125
|
true
|
120
126
|
end
|
@@ -164,28 +170,40 @@ module Crudable
|
|
164
170
|
t('crudable.not_destroyed', model_name: resource_class.model_name.human)
|
165
171
|
end
|
166
172
|
|
167
|
-
def on_successful_create
|
173
|
+
def on_successful_create
|
174
|
+
flash[:success] = after_create_notice
|
175
|
+
end
|
168
176
|
|
169
177
|
def on_successful_create_render
|
170
|
-
redirect_to after_create_redirect_path
|
178
|
+
redirect_to after_create_redirect_path
|
171
179
|
end
|
172
180
|
|
173
181
|
def on_failed_create_setup; end
|
174
182
|
|
175
|
-
def on_successful_update
|
183
|
+
def on_successful_update
|
184
|
+
flash[:success] = after_update_notice
|
185
|
+
end
|
176
186
|
|
177
187
|
def on_successful_update_render
|
178
|
-
redirect_to after_update_redirect_path
|
188
|
+
redirect_to after_update_redirect_path
|
179
189
|
end
|
180
190
|
|
181
191
|
def on_failed_update_setup; end
|
182
192
|
|
193
|
+
def on_successful_destroy
|
194
|
+
flash[:success] = after_destroy_notice
|
195
|
+
end
|
196
|
+
|
197
|
+
def on_failed_destroy
|
198
|
+
flash[:alert] = after_failed_destroy_alert
|
199
|
+
end
|
200
|
+
|
183
201
|
def on_successful_destroy_render
|
184
|
-
redirect_to after_destroy_redirect_path
|
202
|
+
redirect_to after_destroy_redirect_path
|
185
203
|
end
|
186
204
|
|
187
205
|
def on_failed_destroy_render
|
188
|
-
redirect_to after_failed_destroy_redirect_path
|
206
|
+
redirect_to after_failed_destroy_redirect_path
|
189
207
|
end
|
190
208
|
|
191
209
|
def before_authorize_create; end
|
@@ -198,17 +216,43 @@ module Crudable
|
|
198
216
|
|
199
217
|
def on_failed_create_render
|
200
218
|
respond_to do |format|
|
201
|
-
format.turbo_stream
|
219
|
+
format.turbo_stream { render_action(:new) }
|
202
220
|
format.html { render :new, status: :unprocessable_entity }
|
203
221
|
end
|
204
222
|
end
|
205
223
|
|
206
224
|
def on_failed_update_render
|
207
225
|
respond_to do |format|
|
208
|
-
format.turbo_stream
|
226
|
+
format.turbo_stream { render_action(:edit) }
|
209
227
|
format.html { render :edit, status: :unprocessable_entity }
|
210
228
|
end
|
211
229
|
end
|
230
|
+
|
231
|
+
def create_params
|
232
|
+
resource_params
|
233
|
+
end
|
234
|
+
|
235
|
+
def update_params
|
236
|
+
resource_params
|
237
|
+
end
|
238
|
+
|
239
|
+
def resource_params
|
240
|
+
params.require(resource_var_name).permit(*permitted_params)
|
241
|
+
end
|
242
|
+
|
243
|
+
def permitted_params
|
244
|
+
raise NotImplementedError, 'You must implement permitted_params in your controller'
|
245
|
+
end
|
246
|
+
|
247
|
+
def render_action(default_action_name)
|
248
|
+
logger.debug "Rendering relevant action for #{controller_path}/#{default_action_name} as #{request.format.symbol}"
|
249
|
+
return render default_action_name if lookup_context.template_exists?("#{controller_path}/#{default_action_name}")
|
250
|
+
|
251
|
+
Crudable::Rails.deprecator.warn("Rendering fallback: #{action_name}, format: #{request.format.symbol}. Rename your template to #{default_action_name}")
|
252
|
+
|
253
|
+
logger.debug "Rendering fallback: #{action_name}"
|
254
|
+
render
|
255
|
+
end
|
212
256
|
end
|
213
257
|
end
|
214
258
|
end
|
@@ -4,6 +4,10 @@ module Crudable
|
|
4
4
|
ActiveSupport.on_load(:action_controller) do
|
5
5
|
::ActionController::Base.include Crudable::Rails::Controller
|
6
6
|
end
|
7
|
+
|
8
|
+
initializer "crudable-rails.deprecator" do |app|
|
9
|
+
app.deprecators[:crudable_rails] = Crudable::Rails.deprecator
|
10
|
+
end
|
7
11
|
end
|
8
12
|
end
|
9
13
|
end
|
@@ -16,7 +16,7 @@ module Crudable
|
|
16
16
|
|
17
17
|
object_name = Regexp.last_match(1)
|
18
18
|
object_scope = object_name.classify.constantize
|
19
|
-
object_scope =
|
19
|
+
object_scope = object_scope.friendly if friendly_finders?
|
20
20
|
instance_variable_set("@#{object_name}", object_scope.find(value))
|
21
21
|
self.class.send(:decorates_assigned, object_name.to_sym) if defined?(Draper)
|
22
22
|
end
|
data/lib/crudable-rails.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'turbo-rails'
|
2
|
+
|
1
3
|
require 'crudable/rails/version'
|
2
4
|
require 'crudable/rails/engine'
|
3
5
|
require 'crudable/rails/controller'
|
@@ -7,6 +9,8 @@ require 'crudable/rails/nestable'
|
|
7
9
|
|
8
10
|
module Crudable
|
9
11
|
module Rails
|
10
|
-
|
12
|
+
def self.deprecator
|
13
|
+
@deprecator ||= ActiveSupport::Deprecation.new("2.0", "Crudable::Rails")
|
14
|
+
end
|
11
15
|
end
|
12
16
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crudable-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomislav Simnett
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '7.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 9.0.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,6 +27,23 @@ dependencies:
|
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '7.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 9.0.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: turbo-rails
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 2.0.0
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.0.0
|
27
47
|
- !ruby/object:Gem::Dependency
|
28
48
|
name: rubocop
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,6 +51,9 @@ dependencies:
|
|
31
51
|
- - ">="
|
32
52
|
- !ruby/object:Gem::Version
|
33
53
|
version: '1.50'
|
54
|
+
- - "<"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '2.0'
|
34
57
|
type: :development
|
35
58
|
prerelease: false
|
36
59
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,7 +61,34 @@ dependencies:
|
|
38
61
|
- - ">="
|
39
62
|
- !ruby/object:Gem::Version
|
40
63
|
version: '1.50'
|
41
|
-
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '2.0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: mocha
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '2.6'
|
74
|
+
- - "<"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 3.0.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '2.6'
|
84
|
+
- - "<"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 3.0.0
|
87
|
+
description: Crudable Rails provides everything needed to quickly build fully functional
|
88
|
+
CRUD-based controllers in a Rails application. It streamlines resource management,
|
89
|
+
reduces boilerplate, and enforces best practices for handling requests, responses,
|
90
|
+
and strong parameters. Ideal for developers looking to accelerate Rails development
|
91
|
+
while maintaining flexibility and clean architecture.
|
42
92
|
email:
|
43
93
|
- tom@initforthe.com
|
44
94
|
executables: []
|
@@ -69,7 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
119
|
requirements:
|
70
120
|
- - ">="
|
71
121
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
122
|
+
version: 3.0.0
|
73
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
124
|
requirements:
|
75
125
|
- - ">="
|