dry_crud 6.0.0 → 8.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 +4 -4
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -6
- data/VERSION +1 -1
- data/app/assets/stylesheets/sample.scss +45 -24
- data/app/controllers/crud_controller.rb +24 -26
- data/app/controllers/dry_crud/generic_model.rb +6 -12
- data/app/controllers/dry_crud/nestable.rb +1 -4
- data/app/controllers/dry_crud/rememberable.rb +1 -4
- data/app/controllers/dry_crud/render_callbacks.rb +4 -12
- data/app/controllers/dry_crud/searchable.rb +3 -10
- data/app/controllers/dry_crud/sortable.rb +3 -10
- data/app/controllers/list_controller.rb +1 -3
- data/app/helpers/actions_helper.rb +13 -15
- data/app/helpers/dry_crud/form/builder.rb +56 -62
- data/app/helpers/dry_crud/form/control.rb +12 -19
- data/app/helpers/dry_crud/table/actions.rb +15 -20
- data/app/helpers/dry_crud/table/builder.rb +12 -15
- data/app/helpers/dry_crud/table/col.rb +5 -8
- data/app/helpers/dry_crud/table/sorting.rb +3 -6
- data/app/helpers/form_helper.rb +11 -15
- data/app/helpers/format_helper.rb +18 -20
- data/app/helpers/i18n_helper.rb +13 -15
- data/app/helpers/table_helper.rb +16 -19
- data/app/helpers/utility_helper.rb +12 -14
- data/app/views/crud/new.html.erb +1 -1
- data/app/views/crud/new.html.haml +1 -1
- data/app/views/layouts/application.html.erb +8 -6
- data/app/views/layouts/application.html.haml +6 -5
- data/app/views/list/_search.html.erb +1 -3
- data/app/views/list/_search.html.haml +1 -2
- data/app/views/shared/_error_messages.html.erb +2 -2
- data/lib/dry_crud/engine.rb +1 -3
- data/lib/dry_crud.rb +1 -1
- data/lib/generators/dry_crud/dry_crud_generator.rb +18 -18
- data/lib/generators/dry_crud/dry_crud_generator_base.rb +8 -8
- data/lib/generators/dry_crud/file_generator.rb +6 -6
- data/lib/generators/dry_crud/templates/config/initializers/field_error_proc.rb +1 -1
- data/lib/generators/dry_crud/templates/spec/controllers/crud_test_models_controller_spec.rb +122 -122
- data/lib/generators/dry_crud/templates/spec/helpers/dry_crud/form/builder_spec.rb +55 -60
- data/lib/generators/dry_crud/templates/spec/helpers/dry_crud/table/builder_spec.rb +24 -26
- data/lib/generators/dry_crud/templates/spec/helpers/form_helper_spec.rb +16 -18
- data/lib/generators/dry_crud/templates/spec/helpers/format_helper_spec.rb +90 -94
- data/lib/generators/dry_crud/templates/spec/helpers/i18n_helper_spec.rb +33 -34
- data/lib/generators/dry_crud/templates/spec/helpers/table_helper_spec.rb +59 -61
- data/lib/generators/dry_crud/templates/spec/helpers/utility_helper_spec.rb +20 -23
- data/lib/generators/dry_crud/templates/spec/support/crud_controller_examples.rb +66 -68
- data/lib/generators/dry_crud/templates/spec/support/crud_controller_test_helper.rb +11 -13
- data/lib/generators/dry_crud/templates/test/controllers/crud_test_models_controller_test.rb +63 -65
- data/lib/generators/dry_crud/templates/test/helpers/custom_assertions_test.rb +25 -27
- data/lib/generators/dry_crud/templates/test/helpers/dry_crud/form/builder_test.rb +74 -74
- data/lib/generators/dry_crud/templates/test/helpers/dry_crud/table/builder_test.rb +21 -21
- data/lib/generators/dry_crud/templates/test/helpers/form_helper_test.rb +21 -23
- data/lib/generators/dry_crud/templates/test/helpers/format_helper_test.rb +68 -70
- data/lib/generators/dry_crud/templates/test/helpers/i18n_helper_test.rb +26 -28
- data/lib/generators/dry_crud/templates/test/helpers/table_helper_test.rb +28 -30
- data/lib/generators/dry_crud/templates/test/helpers/utility_helper_test.rb +17 -19
- data/lib/generators/dry_crud/templates/test/support/crud_controller_test_helper.rb +13 -15
- data/lib/generators/dry_crud/templates/test/support/crud_test_helper.rb +15 -19
- data/lib/generators/dry_crud/templates/test/support/crud_test_model.rb +9 -14
- data/lib/generators/dry_crud/templates/test/support/crud_test_models_controller.rb +16 -20
- data/lib/generators/dry_crud/templates/test/support/custom_assertions.rb +8 -10
- metadata +9 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 728d9df7af506d9680cf74d6b7031db221a645816ef03307f1f9a8abca8bd40b
|
4
|
+
data.tar.gz: 748c707433dd4dfea6069f482276e48f45124ba3e26d1ba956d78ab3fc629702
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 692538e533f409bee57aa7ebc5ac99d040d3fabd2e376ecd4edf4057f1f8732011f4753178af4abffe36973baa2dad81c9afa5edc55047bf6c93eb68aef2b80b
|
7
|
+
data.tar.gz: 247d2b34b35ec952f334635a50e5bba85733f0ffef5abbc2efcafa5b5a581aca44f188946eab0bdef662734554e87ae268638a1674720df773599135fd4ee9b9
|
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2010-
|
1
|
+
Copyright (c) 2010-2023 Pascal Zumkehr
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
16
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
17
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
18
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
THE SOFTWARE.
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
= DRY CRUD
|
2
2
|
|
3
|
-
{
|
3
|
+
{rdoc-image:https://github.com/codez/dry_crud/actions/workflows/build.yml/badge.svg}[https://github.com/codez/dry_crud/actions/workflows/build.yml]
|
4
|
+
{rdoc-image:https://api.codeclimate.com/v1/badges/ef7488764a0d9805b37d/maintainability}[https://codeclimate.com/github/codez/dry_crud/maintainability]
|
5
|
+
{rdoc-image:https://api.codeclimate.com/v1/badges/ef7488764a0d9805b37d/test_coverage}[https://codeclimate.com/github/codez/dry_crud/test_coverage]
|
4
6
|
|
5
7
|
dry_crud generates simple and extendable controllers, views and helpers that support you to DRY up the CRUD code in your Rails projects. List, search, sort, show, create, edit and destroy any model entries in just 5 minutes. Start with these artifacts and build a clean base to efficiently develop your application upon.
|
6
8
|
|
@@ -33,12 +35,11 @@ To integrate dry_crud into your code, only a few additions are required:
|
|
33
35
|
* Optionally define a +list+ scope in your models to be used in the +index+ action.
|
34
36
|
* Optionally define a +options_list+ scope in your models to be used in select dropdowns.
|
35
37
|
|
36
|
-
From version 5.0 onwards, the major and minor version numbers will be kept in sync with Rails, and only the matching Rails version is supported.
|
37
|
-
|
38
|
+
From version 5.0 onwards, the major and minor version numbers will be kept in sync with Rails, and only the matching Rails version is supported.
|
38
39
|
|
39
40
|
== Background
|
40
41
|
|
41
|
-
In most Rails applications, you have some models that require basic CRUD (create, read, update, delete) functionality. There are various possibilities like Rails scaffolding, {Inherited Resources}[https://github.com/activeadmin/inherited_resources] or {Rails Admin}[https://github.com/
|
42
|
+
In most Rails applications, you have some models that require basic CRUD (create, read, update, delete) functionality. There are various possibilities like Rails scaffolding, {Inherited Resources}[https://github.com/activeadmin/inherited_resources] or {Rails Admin}[https://github.com/railsadminteam/rails_admin]. Still, various parts in your application remain duplicated. While you might pull up common methods into a common superclass controller, most views still contain very similar code. And then you also have to remember the entire API of these frameworks.
|
42
43
|
|
43
44
|
Enter dry_crud.
|
44
45
|
|
@@ -50,7 +51,7 @@ dry_crud is a Rails generator. All code resides in your application and is open
|
|
50
51
|
|
51
52
|
dry_crud does not depend on any other gems, but easily allows you to integrate them in order to unify the behavior of your CRUD controllers. You might even use the gems mentioned above to adapt your generated CrudController base class. All classes come with thorough tests that provide you with a solid foundation for implementing your own adaptions.
|
52
53
|
|
53
|
-
A basic CSS gets you started with your application's layout. For advanced needs, dry_crud supports the styles and classes used in {Bootstrap
|
54
|
+
A basic CSS gets you started with your application's layout. For advanced needs, dry_crud supports the styles and classes used in {Bootstrap}[http://getbootstrap.com]. As the views are generated into your application code, you are free to change the styling to your needs.
|
54
55
|
|
55
56
|
If you find yourself adapting the same parts of dry_crud for your applications over and over, please feel free to {fork me on Github}[http://github.com/codez/dry_crud].
|
56
57
|
|
@@ -161,7 +162,7 @@ To render custom columns, use the +col+ method with an appropriate block:
|
|
161
162
|
t.sortable_attrs(:lastname, :firstname)
|
162
163
|
t.col('', class: 'center') { |entry| image_tag(entry.picture) }
|
163
164
|
t.attr(:street)
|
164
|
-
t.col('Map') { |entry| link_to(entry.city, "http://maps.google.com/?q=#{entry.city}" }
|
165
|
+
t.col('Map') { |entry| link_to(entry.city, "http://maps.google.com/?q=#{entry.city}") }
|
165
166
|
end %>
|
166
167
|
|
167
168
|
For views of subclasses of ListController, you can directly use the +crud_table+ helper method, where you do not have to pass the <tt>@people</tt> list explicitly and actions are added automatically.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
8.0.0
|
@@ -1,8 +1,12 @@
|
|
1
1
|
$container_width: 1000px;
|
2
2
|
$theme_color: #2580a2;
|
3
3
|
|
4
|
-
body,
|
5
|
-
|
4
|
+
body,
|
5
|
+
div,
|
6
|
+
p,
|
7
|
+
td,
|
8
|
+
th {
|
9
|
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
6
10
|
font-size: 14px;
|
7
11
|
line-height: 1.42857;
|
8
12
|
}
|
@@ -101,7 +105,8 @@ table.table {
|
|
101
105
|
}
|
102
106
|
|
103
107
|
/* div rendered if no entries available for list */
|
104
|
-
div.table {
|
108
|
+
div.table {
|
109
|
+
}
|
105
110
|
|
106
111
|
table.table th {
|
107
112
|
background-color: $theme_color;
|
@@ -119,20 +124,21 @@ table.table td {
|
|
119
124
|
padding: 4px 4px;
|
120
125
|
}
|
121
126
|
|
122
|
-
.table-striped thead tr:nth-child(odd),
|
123
|
-
|
127
|
+
.table-striped thead tr:nth-child(odd),
|
128
|
+
.table thead tr:nth-child(even) {
|
129
|
+
background-color: #d0d0d0;
|
124
130
|
}
|
125
131
|
|
126
132
|
.table-striped tr:nth-child(odd) {
|
127
|
-
background-color: #
|
133
|
+
background-color: #f8f8f8;
|
128
134
|
}
|
129
135
|
|
130
136
|
.table-striped tr:nth-child(even) {
|
131
|
-
background-color: #
|
137
|
+
background-color: #f0f0f0;
|
132
138
|
}
|
133
139
|
|
134
140
|
.table-hover tr:hover {
|
135
|
-
background-color: #
|
141
|
+
background-color: #ffffe0;
|
136
142
|
}
|
137
143
|
|
138
144
|
td {
|
@@ -153,7 +159,7 @@ a:hover {
|
|
153
159
|
}
|
154
160
|
|
155
161
|
a:visited {
|
156
|
-
color:
|
162
|
+
color: #2580a2;
|
157
163
|
}
|
158
164
|
|
159
165
|
a img {
|
@@ -213,11 +219,21 @@ a.icon img {
|
|
213
219
|
vertical-align: top;
|
214
220
|
}
|
215
221
|
|
216
|
-
.icon-plus {
|
217
|
-
|
218
|
-
|
219
|
-
.icon-
|
220
|
-
|
222
|
+
.icon-plus {
|
223
|
+
background-image: image-url("actions/add.png");
|
224
|
+
}
|
225
|
+
.icon-trash {
|
226
|
+
background-image: image-url("actions/delete.png");
|
227
|
+
}
|
228
|
+
.icon-pencil {
|
229
|
+
background-image: image-url("actions/edit.png");
|
230
|
+
}
|
231
|
+
.icon-list {
|
232
|
+
background-image: image-url("actions/list.png");
|
233
|
+
}
|
234
|
+
.icon-zoom-in {
|
235
|
+
background-image: image-url("actions/show.png");
|
236
|
+
}
|
221
237
|
|
222
238
|
.form-group {
|
223
239
|
clear: both;
|
@@ -231,34 +247,39 @@ a.icon img {
|
|
231
247
|
padding-top: 3px;
|
232
248
|
}
|
233
249
|
|
234
|
-
input,
|
250
|
+
input,
|
251
|
+
textarea,
|
252
|
+
select {
|
235
253
|
font-family: Verdana, Geneva, Helvetica, Arial, sans-serif;
|
236
254
|
font-size: 14px;
|
237
255
|
}
|
238
256
|
|
239
|
-
input[type=text],
|
257
|
+
input[type="text"],
|
258
|
+
input[type="password"],
|
259
|
+
input[type="email"] {
|
240
260
|
width: 300px;
|
241
261
|
}
|
242
262
|
|
243
|
-
input[type=number] {
|
263
|
+
input[type="number"] {
|
244
264
|
width: 100px;
|
245
265
|
}
|
246
266
|
|
247
|
-
textarea,
|
267
|
+
textarea,
|
268
|
+
select[multiple] {
|
248
269
|
width: 300px;
|
249
270
|
height: 80px;
|
250
271
|
}
|
251
272
|
|
252
|
-
[role=search] [type=search] {
|
273
|
+
[role="search"] [type="search"] {
|
253
274
|
width: 220px;
|
254
275
|
}
|
255
276
|
|
256
277
|
.has-error .control-label {
|
257
|
-
color: #
|
278
|
+
color: #d88;
|
258
279
|
}
|
259
280
|
|
260
281
|
.has-error .form-control {
|
261
|
-
border-color: #
|
282
|
+
border-color: #d88;
|
262
283
|
}
|
263
284
|
|
264
285
|
.input-group-append {
|
@@ -284,7 +305,7 @@ textarea, select[multiple] {
|
|
284
305
|
}
|
285
306
|
|
286
307
|
.alert-danger {
|
287
|
-
border: solid 2px #
|
308
|
+
border: solid 2px #d88;
|
288
309
|
background-color: #fec;
|
289
310
|
}
|
290
311
|
|
@@ -292,11 +313,11 @@ textarea, select[multiple] {
|
|
292
313
|
float: right;
|
293
314
|
}
|
294
315
|
|
295
|
-
.float-
|
316
|
+
.float-end {
|
296
317
|
float: right;
|
297
318
|
}
|
298
319
|
|
299
|
-
.float-
|
320
|
+
.float-start {
|
300
321
|
float: left;
|
301
322
|
}
|
302
323
|
|
@@ -8,7 +8,6 @@
|
|
8
8
|
# With the help of additional callbacks, it is possible to hook into the
|
9
9
|
# action procedures without overriding the entire method.
|
10
10
|
class CrudController < ListController
|
11
|
-
|
12
11
|
class_attribute :permitted_attrs
|
13
12
|
|
14
13
|
# Defines before and after callback hooks for create, update, save and
|
@@ -40,6 +39,11 @@ class CrudController < ListController
|
|
40
39
|
assign_attributes if params[model_identifier]
|
41
40
|
end
|
42
41
|
|
42
|
+
# GET /entries/1/edit
|
43
|
+
#
|
44
|
+
# Display a form to edit an exisiting entry of this model.
|
45
|
+
def edit; end
|
46
|
+
|
43
47
|
# POST /entries
|
44
48
|
# POST /entries.json
|
45
49
|
#
|
@@ -52,22 +56,17 @@ class CrudController < ListController
|
|
52
56
|
# in the given block will take precedence over the one defined here.
|
53
57
|
#
|
54
58
|
# Specify a :location option if you wish to do a custom redirect.
|
55
|
-
def create(options
|
59
|
+
def create(**options, &block)
|
56
60
|
model_class.transaction do
|
57
61
|
assign_attributes
|
58
62
|
created = with_callbacks(:create, :save) { entry.save }
|
59
63
|
respond(created,
|
60
|
-
options.merge(status: :created, render_on_failure: :new),
|
64
|
+
**options.merge(status: :created, render_on_failure: :new),
|
61
65
|
&block)
|
62
66
|
raise ActiveRecord::Rollback unless created
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
66
|
-
# GET /entries/1/edit
|
67
|
-
#
|
68
|
-
# Display a form to edit an exisiting entry of this model.
|
69
|
-
def edit; end
|
70
|
-
|
71
70
|
# PUT /entries/1
|
72
71
|
# PUT /entries/1.json
|
73
72
|
#
|
@@ -80,12 +79,12 @@ class CrudController < ListController
|
|
80
79
|
# in the given block will take precedence over the one defined here.
|
81
80
|
#
|
82
81
|
# Specify a :location option if you wish to do a custom redirect.
|
83
|
-
def update(options
|
82
|
+
def update(**options, &block)
|
84
83
|
model_class.transaction do
|
85
84
|
assign_attributes
|
86
85
|
updated = with_callbacks(:update, :save) { entry.save }
|
87
86
|
respond(updated,
|
88
|
-
options.merge(status: :ok, render_on_failure: :edit),
|
87
|
+
**options.merge(status: :ok, render_on_failure: :edit),
|
89
88
|
&block)
|
90
89
|
raise ActiveRecord::Rollback unless updated
|
91
90
|
end
|
@@ -103,11 +102,11 @@ class CrudController < ListController
|
|
103
102
|
# in the given block will take precedence over the one defined here.
|
104
103
|
#
|
105
104
|
# Specify a :location option if you wish to do a custom redirect.
|
106
|
-
def destroy(options
|
105
|
+
def destroy(**options, &block)
|
107
106
|
model_class.transaction do
|
108
107
|
destroyed = run_callbacks(:destroy) { entry.destroy }
|
109
108
|
respond(destroyed,
|
110
|
-
options.merge(status: :no_content),
|
109
|
+
**options.merge(status: :no_content),
|
111
110
|
&block)
|
112
111
|
raise ActiveRecord::Rollback unless destroyed
|
113
112
|
end
|
@@ -139,7 +138,7 @@ class CrudController < ListController
|
|
139
138
|
|
140
139
|
# The form params for this model.
|
141
140
|
def model_params
|
142
|
-
params.
|
141
|
+
params.expect(model_identifier => permitted_attrs)
|
143
142
|
end
|
144
143
|
|
145
144
|
# Path of the index page to return to.
|
@@ -152,14 +151,14 @@ class CrudController < ListController
|
|
152
151
|
path_args(entry)
|
153
152
|
end
|
154
153
|
|
155
|
-
def respond(success, options)
|
154
|
+
def respond(success, **options)
|
156
155
|
respond_to do |format|
|
157
156
|
yield(format, success) if block_given?
|
158
157
|
if success
|
159
|
-
format.html { redirect_on_success(options) }
|
158
|
+
format.html { redirect_on_success(**options) }
|
160
159
|
format.json { render_success_json(options[:status]) }
|
161
160
|
else
|
162
|
-
format.html { render_or_redirect_on_failure(options) }
|
161
|
+
format.html { render_or_redirect_on_failure(**options) }
|
163
162
|
format.json { render_failure_json }
|
164
163
|
end
|
165
164
|
end
|
@@ -167,16 +166,16 @@ class CrudController < ListController
|
|
167
166
|
|
168
167
|
# If the option :render_on_failure is given, render the corresponding
|
169
168
|
# template, otherwise redirect.
|
170
|
-
def render_or_redirect_on_failure(options)
|
169
|
+
def render_or_redirect_on_failure(**options)
|
171
170
|
if options[:render_on_failure]
|
172
171
|
render options[:render_on_failure]
|
173
172
|
else
|
174
|
-
redirect_on_failure(options)
|
173
|
+
redirect_on_failure(**options)
|
175
174
|
end
|
176
175
|
end
|
177
176
|
|
178
177
|
# Perform a redirect after a successfull operation and set a flash notice.
|
179
|
-
def redirect_on_success(options
|
178
|
+
def redirect_on_success(**options)
|
180
179
|
location = options[:location] ||
|
181
180
|
(entry.destroyed? ? index_path : show_path)
|
182
181
|
flash[:notice] ||= flash_message(:success)
|
@@ -184,9 +183,9 @@ class CrudController < ListController
|
|
184
183
|
end
|
185
184
|
|
186
185
|
# Perform a redirect after a failed operation and set a flash alert.
|
187
|
-
def redirect_on_failure(options
|
186
|
+
def redirect_on_failure(**options)
|
188
187
|
location = options[:location] ||
|
189
|
-
request.env[
|
188
|
+
request.env["HTTP_REFERER"].presence ||
|
190
189
|
index_path
|
191
190
|
flash[:alert] ||= error_messages.presence || flash_message(:failure)
|
192
191
|
redirect_to location
|
@@ -211,17 +210,17 @@ class CrudController < ListController
|
|
211
210
|
# or crud.{action_name}.flash.{state} as fallback.
|
212
211
|
def flash_message(state)
|
213
212
|
scope = "#{action_name}.flash.#{state}"
|
214
|
-
keys = [:"#{controller_name}.#{scope}_html",
|
213
|
+
keys = [ :"#{controller_name}.#{scope}_html",
|
215
214
|
:"#{controller_name}.#{scope}",
|
216
215
|
:"crud.#{scope}_html",
|
217
|
-
:"crud.#{scope}"]
|
216
|
+
:"crud.#{scope}" ]
|
218
217
|
I18n.t(keys.shift, model: full_entry_label, default: keys)
|
219
218
|
end
|
220
219
|
|
221
220
|
# A label for the current entry, including the model name.
|
222
221
|
def full_entry_label
|
223
222
|
# rubocop:disable Rails/OutputSafety
|
224
|
-
"#{models_label(false)} <i>#{ERB::Util.h(entry)}</i>".html_safe
|
223
|
+
"#{models_label(plural: false)} <i>#{ERB::Util.h(entry)}</i>".html_safe
|
225
224
|
# rubocop:enable Rails/OutputSafety
|
226
225
|
end
|
227
226
|
|
@@ -229,7 +228,7 @@ class CrudController < ListController
|
|
229
228
|
def error_messages
|
230
229
|
# rubocop:disable Rails/OutputSafety
|
231
230
|
escaped = entry.errors.full_messages.map { |m| ERB::Util.html_escape(m) }
|
232
|
-
escaped.join(
|
231
|
+
escaped.join("<br/>").html_safe
|
233
232
|
# rubocop:enable Rails/OutputSafety
|
234
233
|
end
|
235
234
|
|
@@ -242,5 +241,4 @@ class CrudController < ListController
|
|
242
241
|
before_render_edit(*methods)
|
243
242
|
end
|
244
243
|
end
|
245
|
-
|
246
244
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module DryCrud
|
2
|
-
|
3
2
|
# Connects the including controller to the model whose name corrsponds to
|
4
3
|
# the controller's name.
|
5
4
|
#
|
@@ -7,15 +6,12 @@ module DryCrud
|
|
7
6
|
# Additional helper methods store and retrieve values in instance variables
|
8
7
|
# named after their class.
|
9
8
|
module GenericModel
|
10
|
-
|
11
9
|
extend ActiveSupport::Concern
|
12
10
|
|
13
11
|
included do
|
14
12
|
helper_method :model_class, :models_label, :path_args
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
delegate :model_class, :models_label, :model_identifier, to: 'self.class'
|
14
|
+
delegate :model_class, :models_label, :model_identifier, to: "self.class"
|
19
15
|
end
|
20
16
|
|
21
17
|
# The scope where model entries will be listed and created.
|
@@ -33,7 +29,7 @@ module DryCrud
|
|
33
29
|
|
34
30
|
# Get the instance variable named after the +model_class+.
|
35
31
|
# If the collection variable is required, pass true as the second argument.
|
36
|
-
def model_ivar_get(plural
|
32
|
+
def model_ivar_get(plural: false)
|
37
33
|
name = ivar_name(model_class)
|
38
34
|
name = name.pluralize if plural
|
39
35
|
name = :"@#{name}"
|
@@ -45,11 +41,11 @@ module DryCrud
|
|
45
41
|
def model_ivar_set(value)
|
46
42
|
name = if value.respond_to?(:klass) # ActiveRecord::Relation
|
47
43
|
ivar_name(value.klass).pluralize
|
48
|
-
|
44
|
+
elsif value.respond_to?(:each) # Array
|
49
45
|
ivar_name(value.first.class).pluralize
|
50
|
-
|
46
|
+
else
|
51
47
|
ivar_name(value.class)
|
52
|
-
|
48
|
+
end
|
53
49
|
instance_variable_set(:"@#{name}", value)
|
54
50
|
end
|
55
51
|
|
@@ -59,7 +55,6 @@ module DryCrud
|
|
59
55
|
|
60
56
|
# Class methods from GenericModel.
|
61
57
|
module ClassMethods
|
62
|
-
|
63
58
|
# The ActiveRecord class of the model.
|
64
59
|
def model_class
|
65
60
|
@model_class ||= controller_name.classify.constantize
|
@@ -72,14 +67,13 @@ module DryCrud
|
|
72
67
|
end
|
73
68
|
|
74
69
|
# A human readable plural name of the model.
|
75
|
-
def models_label(plural
|
70
|
+
def models_label(plural: true)
|
76
71
|
opts = { count: (plural ? 3 : 1) }
|
77
72
|
opts[:default] = model_class.model_name.human.titleize
|
78
73
|
opts[:default] = opts[:default].pluralize if plural
|
79
74
|
|
80
75
|
model_class.model_name.human(opts)
|
81
76
|
end
|
82
|
-
|
83
77
|
end
|
84
78
|
end
|
85
79
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module DryCrud
|
2
|
-
|
3
2
|
# Provides functionality to nest controllers/resources.
|
4
3
|
# If a controller is nested, the parent classes and namespaces
|
5
4
|
# may be defined as an array in the +nesting+ class attribute.
|
@@ -8,7 +7,6 @@ module DryCrud
|
|
8
7
|
# namespace, may define this attribute as follows:
|
9
8
|
# self.nesting = :admin, Country
|
10
9
|
module Nestable
|
11
|
-
|
12
10
|
# Adds the :nesting class attribute and parent helper methods
|
13
11
|
# to the including controller.
|
14
12
|
def self.prepended(klass)
|
@@ -45,7 +43,7 @@ module DryCrud
|
|
45
43
|
|
46
44
|
# An array of objects used in url_for and related functions.
|
47
45
|
def path_args(last)
|
48
|
-
parents + [last]
|
46
|
+
parents + [ last ]
|
49
47
|
end
|
50
48
|
|
51
49
|
# Uses the parent entry (if any) to constrain the model scope.
|
@@ -61,6 +59,5 @@ module DryCrud
|
|
61
59
|
def parent_scope
|
62
60
|
parent.send(model_class.name.underscore.pluralize)
|
63
61
|
end
|
64
|
-
|
65
62
|
end
|
66
63
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module DryCrud
|
2
|
-
|
3
2
|
# Remembers certain params of the index action in order to return
|
4
3
|
# to the same list after an entry was viewed or edited.
|
5
4
|
# If the index is called with a param :returning, the remembered params
|
@@ -11,14 +10,13 @@ module DryCrud
|
|
11
10
|
# The params are stored separately for each different +remember_key+, which
|
12
11
|
# defaults to the current request's path.
|
13
12
|
module Rememberable
|
14
|
-
|
15
13
|
extend ActiveSupport::Concern
|
16
14
|
|
17
15
|
included do
|
18
16
|
class_attribute :remember_params
|
19
17
|
self.remember_params = %w[q sort sort_dir page]
|
20
18
|
|
21
|
-
before_action :handle_remember_params, only: [:index]
|
19
|
+
before_action :handle_remember_params, only: [ :index ]
|
22
20
|
end
|
23
21
|
|
24
22
|
private
|
@@ -61,6 +59,5 @@ module DryCrud
|
|
61
59
|
def remember_key
|
62
60
|
request.path
|
63
61
|
end
|
64
|
-
|
65
62
|
end
|
66
63
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module DryCrud
|
2
|
-
|
3
2
|
# Provide +before_render+ callbacks.
|
4
3
|
module RenderCallbacks
|
5
|
-
|
6
4
|
extend ActiveSupport::Concern
|
7
5
|
|
8
6
|
included do
|
@@ -12,16 +10,14 @@ module DryCrud
|
|
12
10
|
|
13
11
|
# Prepended methods for callbacks.
|
14
12
|
module Prepends
|
15
|
-
|
16
13
|
# Helper method to run +before_render+ callbacks and render the action.
|
17
14
|
# If a callback renders or redirects, the action is not rendered.
|
18
|
-
def render(
|
19
|
-
options = _normalize_render(
|
20
|
-
callback = "render_#{options[:template]}"
|
21
|
-
|
15
|
+
def render(...)
|
16
|
+
options = _normalize_render(...)
|
17
|
+
callback = "render_#{options[:template] || options[:action] || action_name}"
|
22
18
|
run_callbacks(callback) if respond_to?(:"_#{callback}_callbacks", true)
|
23
19
|
|
24
|
-
super
|
20
|
+
super unless performed?
|
25
21
|
end
|
26
22
|
|
27
23
|
private
|
@@ -33,12 +29,10 @@ module DryCrud
|
|
33
29
|
-> { run_callbacks(e, &a) }
|
34
30
|
end.call
|
35
31
|
end
|
36
|
-
|
37
32
|
end
|
38
33
|
|
39
34
|
# Class methods for callbacks.
|
40
35
|
module ClassMethods
|
41
|
-
|
42
36
|
# Defines before callbacks for the render actions.
|
43
37
|
def define_render_callbacks(*actions)
|
44
38
|
args = actions.map { |a| :"render_#{a}" }
|
@@ -58,8 +52,6 @@ module DryCrud
|
|
58
52
|
terminate
|
59
53
|
end
|
60
54
|
end
|
61
|
-
|
62
55
|
end
|
63
|
-
|
64
56
|
end
|
65
57
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module DryCrud
|
2
|
-
|
3
2
|
# The search functionality for the index table.
|
4
3
|
# Define an array of searchable string columns in your subclassing
|
5
4
|
# controllers using the class attribute +search_columns+.
|
6
5
|
module Searchable
|
7
|
-
|
8
6
|
extend ActiveSupport::Concern
|
9
7
|
|
10
8
|
included do
|
@@ -18,7 +16,6 @@ module DryCrud
|
|
18
16
|
|
19
17
|
# Prepended methods for searching.
|
20
18
|
module Prepends
|
21
|
-
|
22
19
|
private
|
23
20
|
|
24
21
|
# Enhance the list entries with an optional search criteria
|
@@ -61,24 +58,20 @@ module DryCrud
|
|
61
58
|
def search_support?
|
62
59
|
search_columns.present?
|
63
60
|
end
|
64
|
-
|
65
61
|
end
|
66
62
|
|
67
63
|
# Class methods for Searchable.
|
68
64
|
module ClassMethods
|
69
|
-
|
70
65
|
# All search columns divided in table and field names.
|
71
66
|
def search_tables_and_fields
|
72
67
|
@search_tables_and_fields ||= search_columns.map do |f|
|
73
|
-
if f.to_s.include?(
|
74
|
-
f.split(
|
68
|
+
if f.to_s.include?(".")
|
69
|
+
f.split(".", 2)
|
75
70
|
else
|
76
|
-
[model_class.table_name, f]
|
71
|
+
[ model_class.table_name, f ]
|
77
72
|
end
|
78
73
|
end
|
79
74
|
end
|
80
|
-
|
81
75
|
end
|
82
|
-
|
83
76
|
end
|
84
77
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module DryCrud
|
2
|
-
|
3
2
|
# Sort functionality for the index table.
|
4
3
|
# Define a default sort expression that is always appended to the
|
5
4
|
# current sort params with the class attribute +default_sort+.
|
6
5
|
module Sortable
|
7
|
-
|
8
6
|
extend ActiveSupport::Concern
|
9
7
|
|
10
8
|
included do
|
@@ -20,7 +18,6 @@ module DryCrud
|
|
20
18
|
|
21
19
|
# Class methods for sorting.
|
22
20
|
module ClassMethods
|
23
|
-
|
24
21
|
# Define a map of (virtual) attributes to SQL order expressions.
|
25
22
|
# May be used for sorting table columns that do not appear directly
|
26
23
|
# in the database table. E.g., map city_id: 'cities.name' to
|
@@ -29,20 +26,18 @@ module DryCrud
|
|
29
26
|
self.sort_mappings_with_indifferent_access =
|
30
27
|
hash.with_indifferent_access
|
31
28
|
end
|
32
|
-
|
33
29
|
end
|
34
30
|
|
35
31
|
# Prepended methods for sorting.
|
36
32
|
module Prepends
|
37
|
-
|
38
33
|
private
|
39
34
|
|
40
35
|
# Enhance the list entries with an optional sort order.
|
41
36
|
def list_entries
|
42
37
|
sortable = sortable?(params[:sort])
|
43
38
|
if sortable || default_sort
|
44
|
-
clause = [sortable ? sort_expression : nil, default_sort]
|
45
|
-
super.reorder(Arel.sql(clause.compact.join(
|
39
|
+
clause = [ sortable ? sort_expression : nil, default_sort ]
|
40
|
+
super.reorder(Arel.sql(clause.compact.join(", ")))
|
46
41
|
else
|
47
42
|
super
|
48
43
|
end
|
@@ -57,7 +52,7 @@ module DryCrud
|
|
57
52
|
|
58
53
|
# The sort direction, either 'asc' or 'desc'.
|
59
54
|
def sort_dir
|
60
|
-
params[:sort_dir] ==
|
55
|
+
params[:sort_dir] == "desc" ? "DESC" : "ASC"
|
61
56
|
end
|
62
57
|
|
63
58
|
# Returns true if the passed attribute is sortable.
|
@@ -66,8 +61,6 @@ module DryCrud
|
|
66
61
|
model_class.column_names.include?(attr.to_s) ||
|
67
62
|
sort_mappings_with_indifferent_access.include?(attr))
|
68
63
|
end
|
69
|
-
|
70
64
|
end
|
71
|
-
|
72
65
|
end
|
73
66
|
end
|