avo 1.16.3 → 1.18.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -13
- data/app/components/avo/fields/common/multiple_file_viewer_component.rb +2 -1
- data/app/components/avo/fields/common/single_file_viewer_component.rb +2 -1
- data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/edit_component.html.erb +1 -1
- data/app/controllers/avo/actions_controller.rb +3 -1
- data/app/packs/entrypoints/application.js +2 -0
- data/app/packs/js/controllers/filter_controller.js +19 -2
- data/config/routes.rb +1 -0
- data/lib/avo/app.rb +2 -2
- data/lib/avo/base_action.rb +4 -2
- data/lib/avo/base_resource.rb +16 -5
- data/lib/avo/engine.rb +0 -1
- data/lib/avo/fields/base_field.rb +18 -4
- data/lib/avo/fields/date_time_field.rb +1 -1
- data/lib/avo/fields/file_field.rb +2 -0
- data/lib/avo/fields/files_field.rb +7 -0
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/action.tt +3 -1
- data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
- data/public/avo-packs/css/application-2b4685ca.css.map +1 -1
- data/public/avo-packs/css/application-2b4685ca.css.map.br +0 -0
- data/public/avo-packs/css/application-2b4685ca.css.map.gz +0 -0
- data/public/avo-packs/js/application-6842378de4da9b615e18.js +26 -0
- data/public/avo-packs/js/{application-124d087ff9491dbf3511.js.LICENSE.txt → application-6842378de4da9b615e18.js.LICENSE.txt} +0 -0
- data/public/avo-packs/js/application-6842378de4da9b615e18.js.br +0 -0
- data/public/avo-packs/js/application-6842378de4da9b615e18.js.gz +0 -0
- data/public/avo-packs/js/application-6842378de4da9b615e18.js.map +1 -0
- data/public/avo-packs/js/application-6842378de4da9b615e18.js.map.br +0 -0
- data/public/avo-packs/js/application-6842378de4da9b615e18.js.map.gz +0 -0
- data/public/avo-packs/manifest.json +8 -8
- metadata +11 -11
- data/public/avo-packs/js/application-124d087ff9491dbf3511.js +0 -26
- data/public/avo-packs/js/application-124d087ff9491dbf3511.js.br +0 -0
- data/public/avo-packs/js/application-124d087ff9491dbf3511.js.gz +0 -0
- data/public/avo-packs/js/application-124d087ff9491dbf3511.js.map +0 -1
- data/public/avo-packs/js/application-124d087ff9491dbf3511.js.map.br +0 -0
- data/public/avo-packs/js/application-124d087ff9491dbf3511.js.map.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccd552281f8ac8b77ea15f6d9000271a447a01190cb3c46905898f94df366009
|
4
|
+
data.tar.gz: c97173ac80821f5ef2de0f3d1060be50fe1c3b2c19d1b2f8eb177c9fc750f2d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84703917f0960fb186bd79b5b7463298afd544e625f0b9ef83af6373c56d673e22479c2e88528cd2df1add04bd2ced0c31d50ea4bc6d856cfb26dd00a07cac42
|
7
|
+
data.tar.gz: f0e6a6d3b59bf79dac877bb012da1f56c979bf72897241e0f9d1633c7745e7fc1ce769d72610105d42b1e37d4a86f19e8a1e39370e709a2be24869a4b7a20981
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.18.0.pre.1)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -107,7 +107,7 @@ GEM
|
|
107
107
|
aws-eventstream (~> 1, >= 1.0.2)
|
108
108
|
bcrypt (3.1.16)
|
109
109
|
bindex (0.8.1)
|
110
|
-
bootsnap (1.
|
110
|
+
bootsnap (1.9.3)
|
111
111
|
msgpack (~> 1.0)
|
112
112
|
breadcrumbs_on_rails (4.0.0)
|
113
113
|
rails (>= 5.0)
|
@@ -123,7 +123,7 @@ GEM
|
|
123
123
|
regexp_parser (~> 1.5)
|
124
124
|
xpath (~> 3.2)
|
125
125
|
childprocess (3.0.0)
|
126
|
-
concurrent-ruby (1.1.
|
126
|
+
concurrent-ruby (1.1.9)
|
127
127
|
countries (3.1.0)
|
128
128
|
i18n_data (~> 0.11.0)
|
129
129
|
sixarm_ruby_unaccent (~> 1.1)
|
@@ -131,7 +131,7 @@ GEM
|
|
131
131
|
crack (0.4.4)
|
132
132
|
crass (1.0.6)
|
133
133
|
database_cleaner (1.8.5)
|
134
|
-
devise (4.
|
134
|
+
devise (4.8.1)
|
135
135
|
bcrypt (~> 3.0)
|
136
136
|
orm_adapter (~> 0.1)
|
137
137
|
railties (>= 4.1.0)
|
@@ -168,7 +168,7 @@ GEM
|
|
168
168
|
httparty (0.18.1)
|
169
169
|
mime-types (~> 3.0)
|
170
170
|
multi_xml (>= 0.5.2)
|
171
|
-
i18n (1.8.
|
171
|
+
i18n (1.8.11)
|
172
172
|
concurrent-ruby (~> 1.0)
|
173
173
|
i18n_data (0.11.0)
|
174
174
|
image_processing (1.12.1)
|
@@ -184,7 +184,7 @@ GEM
|
|
184
184
|
listen (3.5.1)
|
185
185
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
186
186
|
rb-inotify (~> 0.9, >= 0.9.10)
|
187
|
-
loofah (2.
|
187
|
+
loofah (2.13.0)
|
188
188
|
crass (~> 1.0.2)
|
189
189
|
nokogiri (>= 1.5.9)
|
190
190
|
mail (2.7.1)
|
@@ -202,7 +202,7 @@ GEM
|
|
202
202
|
mini_magick (4.11.0)
|
203
203
|
mini_mime (1.0.3)
|
204
204
|
mini_portile2 (2.6.1)
|
205
|
-
minitest (5.
|
205
|
+
minitest (5.15.0)
|
206
206
|
msgpack (1.4.2)
|
207
207
|
multi_xml (0.6.0)
|
208
208
|
nio4r (2.5.8)
|
@@ -210,7 +210,7 @@ GEM
|
|
210
210
|
mini_portile2 (~> 2.6.1)
|
211
211
|
racc (~> 1.4)
|
212
212
|
orm_adapter (0.5.0)
|
213
|
-
pagy (
|
213
|
+
pagy (5.6.6)
|
214
214
|
parallel (1.20.1)
|
215
215
|
parser (3.0.0.0)
|
216
216
|
ast (~> 2.4.1)
|
@@ -220,7 +220,7 @@ GEM
|
|
220
220
|
nio4r (~> 2.0)
|
221
221
|
pundit (2.1.0)
|
222
222
|
activesupport (>= 3.0.0)
|
223
|
-
racc (1.
|
223
|
+
racc (1.6.0)
|
224
224
|
rack (2.2.3)
|
225
225
|
rack-proxy (0.6.5)
|
226
226
|
rack
|
@@ -248,7 +248,7 @@ GEM
|
|
248
248
|
rails-dom-testing (2.0.3)
|
249
249
|
activesupport (>= 4.2.0)
|
250
250
|
nokogiri (>= 1.6)
|
251
|
-
rails-html-sanitizer (1.
|
251
|
+
rails-html-sanitizer (1.4.2)
|
252
252
|
loofah (~> 2.3)
|
253
253
|
railties (6.1.3.2)
|
254
254
|
actionpack (= 6.1.3.2)
|
@@ -257,7 +257,7 @@ GEM
|
|
257
257
|
rake (>= 0.8.7)
|
258
258
|
thor (~> 1.0)
|
259
259
|
rainbow (3.0.0)
|
260
|
-
rake (13.0.
|
260
|
+
rake (13.0.6)
|
261
261
|
ransack (2.4.2)
|
262
262
|
activerecord (>= 5.2.4)
|
263
263
|
activesupport (>= 5.2.4)
|
@@ -379,7 +379,7 @@ GEM
|
|
379
379
|
websocket-extensions (0.1.5)
|
380
380
|
xpath (3.2.0)
|
381
381
|
nokogiri (~> 1.8)
|
382
|
-
zeitwerk (2.
|
382
|
+
zeitwerk (2.5.2)
|
383
383
|
|
384
384
|
PLATFORMS
|
385
385
|
ruby
|
@@ -439,4 +439,4 @@ DEPENDENCIES
|
|
439
439
|
zeitwerk (~> 2.3)
|
440
440
|
|
441
441
|
BUNDLED WITH
|
442
|
-
2.2.
|
442
|
+
2.2.32
|
@@ -3,10 +3,11 @@
|
|
3
3
|
class Avo::Fields::Common::MultipleFileViewerComponent < ViewComponent::Base
|
4
4
|
include Avo::ApplicationHelper
|
5
5
|
|
6
|
-
def initialize(id:, file:, is_image:, resource:, button_size: :md)
|
6
|
+
def initialize(id:, file:, is_image:, direct_upload: false, resource:, button_size: :md)
|
7
7
|
@id = id
|
8
8
|
@file = file
|
9
9
|
@is_image = is_image
|
10
|
+
@direct_upload = direct_upload
|
10
11
|
@button_size = button_size
|
11
12
|
@resource = resource
|
12
13
|
end
|
@@ -3,10 +3,11 @@
|
|
3
3
|
class Avo::Fields::Common::SingleFileViewerComponent < ViewComponent::Base
|
4
4
|
include Avo::ApplicationHelper
|
5
5
|
|
6
|
-
def initialize(id:, file:, is_image:, resource:, button_size: :md)
|
6
|
+
def initialize(id:, file:, is_image:, direct_upload: false, resource:, button_size: :md)
|
7
7
|
@id = id
|
8
8
|
@file = file
|
9
9
|
@is_image = is_image
|
10
|
+
@direct_upload = direct_upload
|
10
11
|
@button_size = button_size
|
11
12
|
@resource = resource
|
12
13
|
end
|
@@ -6,6 +6,6 @@
|
|
6
6
|
<% end %>
|
7
7
|
|
8
8
|
<% if @resource.authorization.authorize_action(:upload_attachments?, raise_exception: false) %>
|
9
|
-
<%= @form.file_field @field.id, disabled: @field.readonly %>
|
9
|
+
<%= @form.file_field @field.id, disabled: @field.readonly, direct_upload: @field.direct_upload %>
|
10
10
|
<% end %>
|
11
11
|
<% end %>
|
@@ -2,6 +2,6 @@
|
|
2
2
|
<%= render Avo::Fields::Common::FilesListViewerComponent.new(field: @field, resource: @resource) if @field.value.present? %>
|
3
3
|
|
4
4
|
<% if @resource.authorization.authorize_action(:upload_attachments?, raise_exception: false) %>
|
5
|
-
<%= @form.file_field @field.id, disabled: @field.readonly, multiple: true %>
|
5
|
+
<%= @form.file_field @field.id, disabled: @field.readonly, multiple: true, direct_upload: @field.direct_upload %>
|
6
6
|
<% end %>
|
7
7
|
<% end %>
|
@@ -2,6 +2,7 @@
|
|
2
2
|
import 'core-js/stable'
|
3
3
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
4
4
|
import 'regenerator-runtime/runtime'
|
5
|
+
import * as ActiveStorage from '@rails/activestorage'
|
5
6
|
import * as Mousetrap from 'mousetrap'
|
6
7
|
import { Application } from 'stimulus'
|
7
8
|
import { Turbo } from '@hotwired/turbo-rails'
|
@@ -32,6 +33,7 @@ function initTippy() {
|
|
32
33
|
window.initTippy = initTippy
|
33
34
|
|
34
35
|
const application = Application.start()
|
36
|
+
ActiveStorage.start()
|
35
37
|
|
36
38
|
const context = require.context('./../js/controllers', true, /\.js$/)
|
37
39
|
application.load(definitionsFromContext(context))
|
@@ -21,6 +21,23 @@ export default class extends Controller {
|
|
21
21
|
return param
|
22
22
|
}
|
23
23
|
|
24
|
+
b64EncodeUnicode(str) {
|
25
|
+
// first we use encodeURIComponent to get percent-encoded UTF-8,
|
26
|
+
// then we convert the percent encodings into raw bytes which
|
27
|
+
// can be fed into btoa.
|
28
|
+
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
|
29
|
+
function toSolidBytes(match, p1) {
|
30
|
+
return String.fromCharCode('0x' + p1);
|
31
|
+
}));
|
32
|
+
}
|
33
|
+
|
34
|
+
b64DecodeUnicode(str) {
|
35
|
+
// Going backwards: from bytestream, to percent-encoding, to original string.
|
36
|
+
return decodeURIComponent(atob(str).split('').map(function(c) {
|
37
|
+
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
38
|
+
}).join(''));
|
39
|
+
}
|
40
|
+
|
24
41
|
changeFilter() {
|
25
42
|
const value = this.getFilterValue()
|
26
43
|
const filterClass = this.getFilterClass()
|
@@ -28,7 +45,7 @@ export default class extends Controller {
|
|
28
45
|
let filters = this.uriParams()[this.uriParam('filters')]
|
29
46
|
|
30
47
|
if (filters) {
|
31
|
-
filters = JSON.parse(
|
48
|
+
filters = JSON.parse(this.b64DecodeUnicode(filters))
|
32
49
|
} else {
|
33
50
|
filters = {}
|
34
51
|
}
|
@@ -46,7 +63,7 @@ export default class extends Controller {
|
|
46
63
|
let encodedFilters
|
47
64
|
|
48
65
|
if (filtered && Object.keys(filtered).length > 0) {
|
49
|
-
encodedFilters =
|
66
|
+
encodedFilters = this.b64EncodeUnicode(JSON.stringify(filtered))
|
50
67
|
}
|
51
68
|
|
52
69
|
const url = new URI(this.urlRedirectTarget.href)
|
data/config/routes.rb
CHANGED
data/lib/avo/app.rb
CHANGED
@@ -32,9 +32,9 @@ module Avo
|
|
32
32
|
|
33
33
|
# Set the current host for ActiveStorage
|
34
34
|
begin
|
35
|
-
ActiveStorage::Current.
|
35
|
+
ActiveStorage::Current.url_options = request.base_url
|
36
36
|
rescue => exception
|
37
|
-
Rails.logger.debug "[Avo] Failed to set ActiveStorage::Current.
|
37
|
+
Rails.logger.debug "[Avo] Failed to set ActiveStorage::Current.url_options, #{exception.inspect}"
|
38
38
|
end
|
39
39
|
|
40
40
|
init_resources
|
data/lib/avo/base_action.rb
CHANGED
@@ -70,7 +70,7 @@ module Avo
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def handle_action(**args)
|
73
|
-
models, fields = args.values_at(:models, :fields)
|
73
|
+
models, fields, current_user, resource = args.values_at(:models, :fields, :current_user, :resource)
|
74
74
|
avo_fields = get_fields.map { |field| [field.id, field] }.to_h
|
75
75
|
|
76
76
|
if fields.present?
|
@@ -84,7 +84,9 @@ module Avo
|
|
84
84
|
end
|
85
85
|
|
86
86
|
args = {
|
87
|
-
fields: processed_fields
|
87
|
+
fields: processed_fields,
|
88
|
+
current_user: current_user,
|
89
|
+
resource: resource,
|
88
90
|
}
|
89
91
|
|
90
92
|
args[:models] = models unless standalone
|
data/lib/avo/base_resource.rb
CHANGED
@@ -16,6 +16,7 @@ module Avo
|
|
16
16
|
class_attribute :includes, default: []
|
17
17
|
class_attribute :model_class
|
18
18
|
class_attribute :translation_key
|
19
|
+
class_attribute :translation_enabled
|
19
20
|
class_attribute :default_view_type, default: :table
|
20
21
|
class_attribute :devise_password_optional, default: false
|
21
22
|
class_attribute :actions_loader
|
@@ -94,7 +95,7 @@ module Avo
|
|
94
95
|
return [] if self.class.fields.blank?
|
95
96
|
|
96
97
|
fields = self.class.fields.map do |field|
|
97
|
-
field.hydrate(resource: self, panel_name: default_panel_name, user: user)
|
98
|
+
field.hydrate(resource: self, panel_name: default_panel_name, user: user, translation_enabled: translation_enabled)
|
98
99
|
end
|
99
100
|
|
100
101
|
if Avo::App.license.lacks_with_trial(:custom_fields)
|
@@ -192,12 +193,16 @@ module Avo
|
|
192
193
|
]
|
193
194
|
end
|
194
195
|
|
196
|
+
def class_name_without_resource
|
197
|
+
self.class.name.demodulize.chomp("Resource")
|
198
|
+
end
|
199
|
+
|
195
200
|
def model_class
|
196
201
|
return self.class.model_class if self.class.model_class.present?
|
197
202
|
|
198
203
|
return @model.class if @model.present?
|
199
204
|
|
200
|
-
|
205
|
+
class_name_without_resource.safe_constantize
|
201
206
|
end
|
202
207
|
|
203
208
|
def model_title
|
@@ -206,12 +211,18 @@ module Avo
|
|
206
211
|
name
|
207
212
|
end
|
208
213
|
|
214
|
+
def translation_key
|
215
|
+
return "avo.resource_translations.#{class_name_without_resource.underscore}" if self.class.translation_enabled
|
216
|
+
|
217
|
+
self.class.translation_key
|
218
|
+
end
|
219
|
+
|
209
220
|
def name
|
210
221
|
return @name if @name.present?
|
211
222
|
|
212
|
-
return I18n.t(
|
223
|
+
return I18n.t(translation_key, count: 1).capitalize if translation_key
|
213
224
|
|
214
|
-
|
225
|
+
class_name_without_resource.titlecase
|
215
226
|
end
|
216
227
|
|
217
228
|
def singular_name
|
@@ -219,7 +230,7 @@ module Avo
|
|
219
230
|
end
|
220
231
|
|
221
232
|
def plural_name
|
222
|
-
return I18n.t(
|
233
|
+
return I18n.t(translation_key, count: 2).capitalize if translation_key
|
223
234
|
|
224
235
|
name.pluralize
|
225
236
|
end
|
data/lib/avo/engine.rb
CHANGED
@@ -6,8 +6,6 @@ module Avo
|
|
6
6
|
include Avo::Fields::FieldExtensions::VisibleInDifferentViews
|
7
7
|
|
8
8
|
attr_reader :id
|
9
|
-
attr_reader :name
|
10
|
-
attr_reader :translation_key
|
11
9
|
attr_reader :block
|
12
10
|
attr_reader :required
|
13
11
|
attr_reader :readonly
|
@@ -43,8 +41,9 @@ module Avo
|
|
43
41
|
super(id, **args, &block)
|
44
42
|
|
45
43
|
@id = id
|
46
|
-
@name = args[:name]
|
44
|
+
@name = args[:name]
|
47
45
|
@translation_key = args[:translation_key]
|
46
|
+
@translation_enabled = false
|
48
47
|
@block = block
|
49
48
|
@required = args[:required] || false
|
50
49
|
@readonly = args[:readonly] || false
|
@@ -72,17 +71,32 @@ module Avo
|
|
72
71
|
except_on args[:except_on] if args[:except_on].present?
|
73
72
|
end
|
74
73
|
|
75
|
-
def hydrate(model: nil, resource: nil, action: nil, view: nil, panel_name: nil, user: nil)
|
74
|
+
def hydrate(model: nil, resource: nil, action: nil, view: nil, panel_name: nil, user: nil, translation_enabled: nil)
|
76
75
|
@model = model if model.present?
|
77
76
|
@view = view if view.present?
|
78
77
|
@resource = resource if resource.present?
|
79
78
|
@action = action if action.present?
|
80
79
|
@user = user if user.present?
|
81
80
|
@panel_name = panel_name if panel_name.present?
|
81
|
+
@translation_enabled = translation_enabled if translation_enabled.present?
|
82
82
|
|
83
83
|
self
|
84
84
|
end
|
85
85
|
|
86
|
+
def translation_key
|
87
|
+
return "avo.field_translations.#{@id}" if @translation_enabled
|
88
|
+
|
89
|
+
@translation_key
|
90
|
+
end
|
91
|
+
|
92
|
+
def name
|
93
|
+
return @name if @name.present?
|
94
|
+
|
95
|
+
return I18n.t(translation_key, count: 1).capitalize if translation_key
|
96
|
+
|
97
|
+
@id.to_s.humanize(keep_id_suffix: true)
|
98
|
+
end
|
99
|
+
|
86
100
|
def visible?
|
87
101
|
if visible.present? && visible.respond_to?(:call)
|
88
102
|
visible.call resource: @resource
|
@@ -17,7 +17,7 @@ module Avo
|
|
17
17
|
return nil if value.nil?
|
18
18
|
|
19
19
|
if @format.is_a?(Symbol)
|
20
|
-
value.to_time.in_time_zone(timezone).
|
20
|
+
value.to_time.in_time_zone(timezone).to_formatted_s(@format)
|
21
21
|
else
|
22
22
|
value.to_time.in_time_zone(timezone).strftime(@format)
|
23
23
|
end
|
@@ -4,6 +4,7 @@ module Avo
|
|
4
4
|
attr_accessor :link_to_resource
|
5
5
|
attr_accessor :is_avatar
|
6
6
|
attr_accessor :is_image
|
7
|
+
attr_accessor :direct_upload
|
7
8
|
|
8
9
|
def initialize(id, **args, &block)
|
9
10
|
super(id, **args, &block)
|
@@ -11,6 +12,7 @@ module Avo
|
|
11
12
|
@link_to_resource = args[:link_to_resource].present? ? args[:link_to_resource] : false
|
12
13
|
@is_avatar = args[:is_avatar].present? ? args[:is_avatar] : false
|
13
14
|
@is_image = args[:is_image].present? ? args[:is_image] : @is_avatar
|
15
|
+
@direct_upload = args[:direct_upload].present? ? args[:direct_upload] : false
|
14
16
|
end
|
15
17
|
|
16
18
|
def path
|
@@ -2,11 +2,13 @@ module Avo
|
|
2
2
|
module Fields
|
3
3
|
class FilesField < BaseField
|
4
4
|
attr_accessor :is_image
|
5
|
+
attr_accessor :direct_upload
|
5
6
|
|
6
7
|
def initialize(id, **args, &block)
|
7
8
|
super(id, **args, &block)
|
8
9
|
|
9
10
|
@is_image = args[:is_image].present? ? args[:is_image] : @is_avatar
|
11
|
+
@direct_upload = args[:direct_upload].present? ? args[:direct_upload] : false
|
10
12
|
end
|
11
13
|
|
12
14
|
def view_component_name
|
@@ -21,6 +23,11 @@ module Avo
|
|
21
23
|
return model unless model.methods.include? key.to_sym
|
22
24
|
|
23
25
|
value.each do |file|
|
26
|
+
# Skip empty values
|
27
|
+
next unless file.present?
|
28
|
+
# Skip Capybara Nil files in tests
|
29
|
+
next unless file.class === Capybara::RackTest::Form::NilUploadedFile
|
30
|
+
|
24
31
|
model.send(key).attach file
|
25
32
|
end
|
26
33
|
|
data/lib/avo/version.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
class <%= class_name.camelize %> < Avo::BaseAction
|
2
2
|
self.name = '<%= name.underscore.humanize %>'
|
3
3
|
|
4
|
-
def handle(
|
4
|
+
def handle(**args)
|
5
|
+
models, fields, current_user, resource = args.values_at(:models, :fields, :current_user, :resource)
|
6
|
+
|
5
7
|
models.each do |model|
|
6
8
|
# Do something with your models.
|
7
9
|
end
|