crudable-rails 1.0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +3 -0
- data/config/locales/en.yml +6 -0
- data/lib/crudable/rails/base.rb +214 -0
- data/lib/crudable/rails/controller.rb +17 -0
- data/lib/crudable/rails/engine.rb +9 -0
- data/lib/crudable/rails/nestable.rb +26 -0
- data/lib/crudable/rails/resourceable.rb +70 -0
- data/lib/crudable/rails/version.rb +8 -0
- data/lib/crudable-rails.rb +12 -0
- data/lib/tasks/crudable_tasks.rake +4 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c3bce80de66d640b96222a505af0357771fe9657d14ae853649bbdf7c78778bc
|
4
|
+
data.tar.gz: 435d8c280e42996182578d23065d2905ca39aa6608e324b410eac295933a33aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: be090adbbbf6dce74144fa5c5ee435fb17f85dc674505ab4244101db8bbdb35cb634a8da2e662f76e83dca14d0b411effbcad0dafa263ca98c1c044e0f1e84f6
|
7
|
+
data.tar.gz: 1175cca36ec335d808dbe2f7740efd2e9c6043b58b7cf45a7fbe753f0e315b7873a44fbf9ee56256766157468a4b92855a48c44ce8f1c7001bf66959efe3b104
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2023 Tomislav Simnett
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Crudable
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "crudable"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install crudable
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crudable
|
4
|
+
module Rails
|
5
|
+
module Base
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include Crudable::Rails::Resourceable
|
10
|
+
|
11
|
+
before_action :find_resource, only: %i[show edit update destroy]
|
12
|
+
after_action :authorize_resource, only: %i[new show edit] if defined?(Pundit)
|
13
|
+
|
14
|
+
decorates_assigned plural_resource_var_name.to_sym, resource_var_name.to_sym if defined?(Draper)
|
15
|
+
end
|
16
|
+
|
17
|
+
def index
|
18
|
+
instance_variable_set("@#{plural_resource_var_name}", resource_scope)
|
19
|
+
paginate_resource
|
20
|
+
end
|
21
|
+
|
22
|
+
def show; end
|
23
|
+
|
24
|
+
def new
|
25
|
+
instance_variable_set("@#{resource_var_name}", resource_class.new)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create # rubocop:disable Metrics/MethodLength
|
29
|
+
instance_variable_set("@#{resource_var_name}", resource_class.new(create_params)) unless skip_initialize_create?
|
30
|
+
before_authorize_create
|
31
|
+
authorize_resource
|
32
|
+
after_authorize_create
|
33
|
+
if instance_variable_get("@#{resource_var_name}").save
|
34
|
+
on_successful_create
|
35
|
+
on_successful_create_render
|
36
|
+
else
|
37
|
+
on_failed_create_setup
|
38
|
+
on_failed_create_render
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def edit; end
|
43
|
+
|
44
|
+
def update
|
45
|
+
before_authorize_update
|
46
|
+
authorize_resource
|
47
|
+
after_authorize_update
|
48
|
+
if instance_variable_get("@#{resource_var_name}").update update_params
|
49
|
+
on_successful_update
|
50
|
+
on_successful_update_render
|
51
|
+
else
|
52
|
+
on_failed_update_setup
|
53
|
+
on_failed_update_render
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def destroy
|
58
|
+
authorize_resource(destroy_method)
|
59
|
+
if instance_variable_get("@#{resource_var_name}").send(destroy_method)
|
60
|
+
on_successful_destroy_render
|
61
|
+
else
|
62
|
+
on_failed_destroy_render
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def destroy_method
|
69
|
+
return :destroy unless defined?(Discard)
|
70
|
+
return :destroy if params[:destroy]
|
71
|
+
|
72
|
+
@destroy_method ||= discard? && !instance_variable_get("@#{resource_var_name}").discarded? ? :discard : :destroy
|
73
|
+
end
|
74
|
+
|
75
|
+
def discard?
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
def find_resource
|
80
|
+
resource = friendly_finders? ? resource_class.friendly : resource_class
|
81
|
+
instance = singleton? ? resource.first : resource.find(params[finder_param])
|
82
|
+
|
83
|
+
return redirect_to (resource_namespace + [instance]), status: :moved_permanently if should_redirect?(instance)
|
84
|
+
|
85
|
+
instance_variable_set("@#{resource_var_name}", instance)
|
86
|
+
end
|
87
|
+
|
88
|
+
def should_redirect?(instance)
|
89
|
+
friendly_finders? && request.path != polymorphic_path(resource_namespace + [instance])
|
90
|
+
end
|
91
|
+
|
92
|
+
def singleton?
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
96
|
+
def finder_param
|
97
|
+
:id
|
98
|
+
end
|
99
|
+
|
100
|
+
def resource_scope
|
101
|
+
return apply_scopes(authorizable_scope) if defined?(HasScope)
|
102
|
+
|
103
|
+
authorizable_scope
|
104
|
+
end
|
105
|
+
|
106
|
+
def authorizable_scope
|
107
|
+
defined?(Pundit) ? policy_scope(resource_class) : resource_class.all
|
108
|
+
end
|
109
|
+
|
110
|
+
def paginate_resource?
|
111
|
+
return false unless defined?(Kaminari)
|
112
|
+
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
def friendly_finders?
|
117
|
+
return false unless defined?(FriendlyId) && object_class.respond_to?(:friendly)
|
118
|
+
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
122
|
+
def skip_initialize_create?
|
123
|
+
false
|
124
|
+
end
|
125
|
+
|
126
|
+
def paginate_resource
|
127
|
+
return unless paginate_resource?
|
128
|
+
|
129
|
+
instance_variable_set(
|
130
|
+
"@#{plural_resource_var_name}",
|
131
|
+
instance_variable_get("@#{plural_resource_var_name}").page(params[:page]).per(params[:per])
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
135
|
+
def after_create_redirect_path
|
136
|
+
resource_namespace + [plural_resource_var_name.to_sym]
|
137
|
+
end
|
138
|
+
|
139
|
+
def after_create_notice
|
140
|
+
t('crudable.created', model_name: resource_class.model_name.human)
|
141
|
+
end
|
142
|
+
|
143
|
+
def after_update_redirect_path
|
144
|
+
resource_namespace + [instance_variable_get("@#{resource_var_name}")]
|
145
|
+
end
|
146
|
+
|
147
|
+
def after_update_notice
|
148
|
+
t('crudable.updated', model_name: resource_class.model_name.human)
|
149
|
+
end
|
150
|
+
|
151
|
+
def after_destroy_redirect_path
|
152
|
+
resource_namespace + [plural_resource_var_name.to_sym]
|
153
|
+
end
|
154
|
+
|
155
|
+
def after_failed_destroy_redirect_path
|
156
|
+
after_destroy_redirect_path
|
157
|
+
end
|
158
|
+
|
159
|
+
def after_destroy_notice
|
160
|
+
t('crudable.destroyed', model_name: resource_class.model_name.human)
|
161
|
+
end
|
162
|
+
|
163
|
+
def after_failed_destroy_alert
|
164
|
+
t('crudable.not_destroyed', model_name: resource_class.model_name.human)
|
165
|
+
end
|
166
|
+
|
167
|
+
def on_successful_create; end
|
168
|
+
|
169
|
+
def on_successful_create_render
|
170
|
+
redirect_to after_create_redirect_path, success: after_create_notice
|
171
|
+
end
|
172
|
+
|
173
|
+
def on_failed_create_setup; end
|
174
|
+
|
175
|
+
def on_successful_update; end
|
176
|
+
|
177
|
+
def on_successful_update_render
|
178
|
+
redirect_to after_update_redirect_path, success: after_update_notice
|
179
|
+
end
|
180
|
+
|
181
|
+
def on_failed_update_setup; end
|
182
|
+
|
183
|
+
def on_successful_destroy_render
|
184
|
+
redirect_to after_destroy_redirect_path, success: after_destroy_notice
|
185
|
+
end
|
186
|
+
|
187
|
+
def on_failed_destroy_render
|
188
|
+
redirect_to after_failed_destroy_redirect_path, alert: after_failed_destroy_alert
|
189
|
+
end
|
190
|
+
|
191
|
+
def before_authorize_create; end
|
192
|
+
|
193
|
+
def before_authorize_update; end
|
194
|
+
|
195
|
+
def after_authorize_create; end
|
196
|
+
|
197
|
+
def after_authorize_update; end
|
198
|
+
|
199
|
+
def on_failed_create_render
|
200
|
+
respond_to do |format|
|
201
|
+
format.turbo_stream
|
202
|
+
format.html { render :new, status: :unprocessable_entity }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def on_failed_update_render
|
207
|
+
respond_to do |format|
|
208
|
+
format.turbo_stream
|
209
|
+
format.html { render :edit, status: :unprocessable_entity }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crudable
|
4
|
+
module Rails
|
5
|
+
# Include Crudable Controller Class Methods
|
6
|
+
module Controller
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def crudable(nested: false)
|
11
|
+
include Crudable::Rails::Base
|
12
|
+
include Crudable::Rails::Nestable if nested
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crudable
|
4
|
+
module Rails
|
5
|
+
# Nestable Module
|
6
|
+
module Nestable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
before_action :find_parent, only: %i[index new create]
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_parent
|
14
|
+
params.each do |name, value|
|
15
|
+
next unless name =~ /(.+)_id$/
|
16
|
+
|
17
|
+
object_name = Regexp.last_match(1)
|
18
|
+
object_scope = object_name.classify.constantize
|
19
|
+
object_scope = object_class.friendly if friendly_finders?
|
20
|
+
instance_variable_set("@#{object_name}", object_scope.find(value))
|
21
|
+
self.class.send(:decorates_assigned, object_name.to_sym) if defined?(Draper)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crudable
|
4
|
+
module Rails
|
5
|
+
# Resourceable
|
6
|
+
#
|
7
|
+
# Provides a number of resource helpers for controllers supporting Crudable
|
8
|
+
module Resourceable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
def resource_name
|
12
|
+
self.class.name.split('::').last.gsub('Controller', '').singularize
|
13
|
+
end
|
14
|
+
|
15
|
+
def resource_human_name
|
16
|
+
resource_name.humanize
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_class
|
20
|
+
resource_name.constantize
|
21
|
+
end
|
22
|
+
|
23
|
+
def resource_var_name
|
24
|
+
resource_name.underscore
|
25
|
+
end
|
26
|
+
|
27
|
+
def plural_resource_var_name
|
28
|
+
resource_name.pluralize.underscore
|
29
|
+
end
|
30
|
+
|
31
|
+
def resource_namespace
|
32
|
+
namespaces = self.class.name.split('::')
|
33
|
+
namespaces.pop
|
34
|
+
namespaces.map { |n| n.downcase.to_sym }
|
35
|
+
end
|
36
|
+
|
37
|
+
def authorize_resource(method = action_name)
|
38
|
+
authorize authorizable_resource, "#{method}?".to_sym
|
39
|
+
end
|
40
|
+
|
41
|
+
def authorizable_resource
|
42
|
+
instance_variable_get("@#{resource_var_name}")
|
43
|
+
end
|
44
|
+
|
45
|
+
class_methods do
|
46
|
+
def resource_name
|
47
|
+
name.split('::').last.gsub('Controller', '').singularize
|
48
|
+
end
|
49
|
+
|
50
|
+
def resource_class
|
51
|
+
resource_name.constantize
|
52
|
+
end
|
53
|
+
|
54
|
+
def resource_var_name
|
55
|
+
resource_name.underscore
|
56
|
+
end
|
57
|
+
|
58
|
+
def plural_resource_var_name
|
59
|
+
resource_name.pluralize.underscore
|
60
|
+
end
|
61
|
+
|
62
|
+
def resource_namespace
|
63
|
+
namespaces = name.split('::')
|
64
|
+
namespaces.pop
|
65
|
+
namespaces.map { |n| n.downcase.to_sym }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'crudable/rails/version'
|
2
|
+
require 'crudable/rails/engine'
|
3
|
+
require 'crudable/rails/controller'
|
4
|
+
require 'crudable/rails/base'
|
5
|
+
require 'crudable/rails/resourceable'
|
6
|
+
require 'crudable/rails/nestable'
|
7
|
+
|
8
|
+
module Crudable
|
9
|
+
module Rails
|
10
|
+
# Your code goes here...
|
11
|
+
end
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crudable-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tomislav Simnett
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-10-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.50'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.50'
|
41
|
+
description: CRUD operations for Rails controllers
|
42
|
+
email:
|
43
|
+
- tom@initforthe.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- MIT-LICENSE
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- config/locales/en.yml
|
52
|
+
- lib/crudable-rails.rb
|
53
|
+
- lib/crudable/rails/base.rb
|
54
|
+
- lib/crudable/rails/controller.rb
|
55
|
+
- lib/crudable/rails/engine.rb
|
56
|
+
- lib/crudable/rails/nestable.rb
|
57
|
+
- lib/crudable/rails/resourceable.rb
|
58
|
+
- lib/crudable/rails/version.rb
|
59
|
+
- lib/tasks/crudable_tasks.rake
|
60
|
+
homepage: https://gitlab.com/initforthe/crudable-rails
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.3.26
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: CRUD operations for Rails controllers
|
83
|
+
test_files: []
|