active_scaffold 4.4.1 → 4.4.5
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/CHANGELOG.rdoc +57 -0
- data/app/assets/javascripts/active_scaffold/active_scaffold.js +5 -3
- data/app/assets/javascripts/active_scaffold/load.js +41 -22
- data/lib/active_scaffold/attribute_params.rb +56 -8
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +23 -7
- data/lib/active_scaffold/constraints.rb +3 -2
- data/lib/active_scaffold/helpers/association_helpers.rb +7 -1
- data/lib/active_scaffold/helpers/form_column_helpers.rb +49 -5
- data/lib/active_scaffold/helpers/search_column_helpers.rb +2 -2
- data/lib/active_scaffold/helpers/view_helpers.rb +6 -1
- data/lib/active_scaffold/version.rb +1 -1
- data/lib/active_scaffold.rb +29 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 53bf726d56ef1da11ee5ecdf4bc039b59ef10e74dd1ac9d31e2723e3e27716e1
|
|
4
|
+
data.tar.gz: 625f6798df882567a08bac210c6af4c9dbb246364ba739fc0a68bdad695c7b94
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1948177220ec25858dc4d4a19e0313db67f8cafc544ab6bfdf5129bbd418918c9d6f4e4af1f134213e39cc97fb2da485972feca80628547f7fcbc9ad1687e2b9
|
|
7
|
+
data.tar.gz: 21308ad93ecc7bed4293d82dc4b011eb516e43171d9283ea26fdf24fd67f3283f280ba2c11033c3fdd1008194fef34821a9b134b2c672c8159611eb1b73eac59
|
data/CHANGELOG.rdoc
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
|
+
= 4.4.5
|
|
2
|
+
- Authorize the PaperTrail deleted-records action and allow overriding its version query with +deleted_records_query+
|
|
3
|
+
- Deprecate passing optional boolean arguments positionally; keyword arguments will be required in 4.5.
|
|
4
|
+
|
|
5
|
+
Overrides which only forward arguments can replace anonymous +*+ with +...+. This accepts the positional argument from 4.4 and forwards the keyword argument used by 4.5:
|
|
6
|
+
|
|
7
|
+
# Before
|
|
8
|
+
def find_or_create_for_params(params, parent_column, parent_record, *)
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Compatible with both 4.4 and 4.5
|
|
13
|
+
def find_or_create_for_params(params, parent_column, parent_record, ...)
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
An override which reads or changes the optional argument must temporarily accept both forms. It must call +super+ explicitly with keywords; bare +super+ would forward the original positional arguments and keep producing the warning:
|
|
18
|
+
|
|
19
|
+
# Before
|
|
20
|
+
def update_columns_options(column, scope, options, force = false)
|
|
21
|
+
super(column, scope, options, true)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Compatible with both 4.4 and 4.5
|
|
25
|
+
def update_columns_options(column, scope, options, *legacy_force, force: false, **kwargs)
|
|
26
|
+
force = legacy_force.first unless legacy_force.empty?
|
|
27
|
+
force = true
|
|
28
|
+
super(column, scope, options, force: force, **kwargs)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
After requiring ActiveScaffold 4.5, the compatibility rest argument can be removed:
|
|
32
|
+
|
|
33
|
+
def update_columns_options(column, scope, options, force: false, **kwargs)
|
|
34
|
+
super(column, scope, options, force: true, **kwargs)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
For methods such as +form_attribute+, where another positional argument followed the boolean, normalize both arguments before calling +super+:
|
|
38
|
+
|
|
39
|
+
def form_attribute(column, record, scope = nil, *legacy_arguments,
|
|
40
|
+
only_value: false, col_class: nil, **kwargs)
|
|
41
|
+
only_value = legacy_arguments.shift unless legacy_arguments.empty?
|
|
42
|
+
col_class = legacy_arguments.shift unless legacy_arguments.empty?
|
|
43
|
+
|
|
44
|
+
super(column, record, scope, only_value: only_value, col_class: col_class, **kwargs)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
= 4.4.4
|
|
48
|
+
- Fix the inconsistent behaviour for constraints containing an array with only one value
|
|
49
|
+
- Wait for dynamically loaded plugins and bridges to finish registering their ready and setup callbacks before initial setup, fixing initialization on directly rendered forms
|
|
50
|
+
- Show all association records in select and multi-select search UIs instead of applying form association conditions
|
|
51
|
+
|
|
52
|
+
= 4.4.3 (yanked)
|
|
53
|
+
- Yanked because it accidentally included unreleased 4.5 functionality
|
|
54
|
+
|
|
55
|
+
= 4.4.2 (yanked)
|
|
56
|
+
- Yanked because it accidentally included unreleased 4.5 functionality
|
|
57
|
+
|
|
1
58
|
= 4.4.1
|
|
2
59
|
- Avoid unnecessary DISTINCT in searches without joins or with only belongs_to joins, fixing PostgreSQL searches on models with json columns
|
|
3
60
|
- Update install generator for the supported rails versions and asset pipelines
|
|
@@ -1695,8 +1695,10 @@
|
|
|
1695
1695
|
|
|
1696
1696
|
// call setup on document.ready if Turbolinks not enabled
|
|
1697
1697
|
if ((typeof(Turbolinks) == 'undefined' || !Turbolinks.supported) && typeof(Turbo) == 'undefined') {
|
|
1698
|
-
ActiveScaffold.
|
|
1699
|
-
|
|
1698
|
+
if (!ActiveScaffold.config.deferInitialSetup) {
|
|
1699
|
+
ActiveScaffold.setup_history_state();
|
|
1700
|
+
ActiveScaffold.setup(document);
|
|
1701
|
+
}
|
|
1700
1702
|
}
|
|
1701
1703
|
if (ActiveScaffold.config.warn_changes) ActiveScaffold.setup_warn_changes();
|
|
1702
1704
|
jQuery(document).on('as:element_updated as:element_created', function(e, action_link) {
|
|
@@ -1732,7 +1734,7 @@
|
|
|
1732
1734
|
});
|
|
1733
1735
|
|
|
1734
1736
|
jQuery(document).on('turbolinks:load turbo:load', function($) {
|
|
1735
|
-
ActiveScaffold.setup(document);
|
|
1737
|
+
if (!ActiveScaffold.config.deferInitialSetup) ActiveScaffold.setup(document);
|
|
1736
1738
|
});
|
|
1737
1739
|
jQuery(window).on('scroll resize', ActiveScaffold.update_floating_form_footer);
|
|
1738
1740
|
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// ActiveScaffold main entry point
|
|
2
2
|
(function() {
|
|
3
3
|
const config = window.ActiveScaffold?.config || {};
|
|
4
|
+
config.deferInitialSetup = true;
|
|
5
|
+
const scriptLoads = new Map();
|
|
6
|
+
const readyHeld = typeof window.jQuery?.holdReady === 'function';
|
|
7
|
+
if (readyHeld) window.jQuery.holdReady(true);
|
|
4
8
|
|
|
5
9
|
// Load dependencies based on configuration
|
|
6
10
|
const loadDependencies = async () => {
|
|
@@ -17,23 +21,14 @@
|
|
|
17
21
|
await loadScript(RAILS_ASSET_URL('/active_scaffold/active_scaffold.js'));
|
|
18
22
|
await loadScript(RAILS_ASSET_URL('/active_scaffold/jquery.editinplace.js'));
|
|
19
23
|
|
|
20
|
-
// Load plugins
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Load bridges
|
|
28
|
-
if (config.bridges) {
|
|
29
|
-
for (const bridge of config.bridges) {
|
|
30
|
-
await loadScript(bridge);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
24
|
+
// Load plugins and bridges in order. Some of them depend on scripts loaded
|
|
25
|
+
// before them and register callbacks while they are being evaluated.
|
|
26
|
+
await loadScripts(config.plugins);
|
|
27
|
+
await loadScripts(config.bridges);
|
|
33
28
|
|
|
34
29
|
// ALL DEPENDENCIES ARE LOADED NOW
|
|
35
30
|
// Initialize everything
|
|
36
|
-
initializeActiveScaffold();
|
|
31
|
+
await initializeActiveScaffold();
|
|
37
32
|
};
|
|
38
33
|
|
|
39
34
|
const loadJQueryUI = async () => {
|
|
@@ -57,8 +52,16 @@
|
|
|
57
52
|
initializeJQueryUI();
|
|
58
53
|
};
|
|
59
54
|
|
|
55
|
+
const loadScripts = async (paths = []) => {
|
|
56
|
+
for (const path of paths || []) {
|
|
57
|
+
await loadScript(path);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
60
61
|
const loadScript = (path) => {
|
|
61
|
-
|
|
62
|
+
if (scriptLoads.has(path)) return scriptLoads.get(path);
|
|
63
|
+
|
|
64
|
+
const promise = new Promise((resolve, reject) => {
|
|
62
65
|
// Check if already loaded
|
|
63
66
|
if (document.querySelector(`script[src*="${path}"]`)) {
|
|
64
67
|
resolve();
|
|
@@ -72,6 +75,9 @@
|
|
|
72
75
|
script.onerror = reject;
|
|
73
76
|
document.head.appendChild(script);
|
|
74
77
|
});
|
|
78
|
+
|
|
79
|
+
scriptLoads.set(path, promise);
|
|
80
|
+
return promise;
|
|
75
81
|
};
|
|
76
82
|
|
|
77
83
|
const initializeJQueryUI = function() {
|
|
@@ -100,13 +106,26 @@
|
|
|
100
106
|
}
|
|
101
107
|
};
|
|
102
108
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (window.jQuery) {
|
|
107
|
-
|
|
109
|
+
// Initialize only after plugins and bridges are available. This is especially
|
|
110
|
+
// important when this file is loaded as a regular script after DOM ready.
|
|
111
|
+
const initializeActiveScaffold = () => new Promise((resolve) => {
|
|
112
|
+
if (!window.jQuery || !window.ActiveScaffold) {
|
|
113
|
+
resolve();
|
|
114
|
+
return;
|
|
108
115
|
}
|
|
109
|
-
|
|
116
|
+
|
|
117
|
+
jQuery(function() {
|
|
118
|
+
config.deferInitialSetup = false;
|
|
119
|
+
if ((typeof(Turbolinks) == 'undefined' || !Turbolinks.supported) && typeof(Turbo) == 'undefined') {
|
|
120
|
+
ActiveScaffold.setup_history_state();
|
|
121
|
+
}
|
|
122
|
+
ActiveScaffold.setup(document);
|
|
123
|
+
jQuery(document).trigger('active-scaffold:loaded');
|
|
124
|
+
resolve();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (readyHeld) window.jQuery.holdReady(false);
|
|
128
|
+
});
|
|
110
129
|
|
|
111
130
|
// Start loading when DOM is ready
|
|
112
131
|
if (document.readyState === 'loading') {
|
|
@@ -114,4 +133,4 @@
|
|
|
114
133
|
} else {
|
|
115
134
|
loadDependencies();
|
|
116
135
|
}
|
|
117
|
-
})();
|
|
136
|
+
})();
|
|
@@ -57,7 +57,13 @@ module ActiveScaffold
|
|
|
57
57
|
#
|
|
58
58
|
# This is a secure way to apply params to a record, because it's based on a loop over the columns
|
|
59
59
|
# set. The columns set will not yield unauthorized columns, and it will not yield unregistered columns.
|
|
60
|
-
def update_record_from_params(parent_record, columns, attributes,
|
|
60
|
+
def update_record_from_params(parent_record, columns, attributes,
|
|
61
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
62
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN, search_attributes: false)
|
|
63
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
64
|
+
positional_avoid_changes, avoid_changes,
|
|
65
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
66
|
+
)
|
|
61
67
|
crud_type = parent_record.new_record? ? :create : :update
|
|
62
68
|
return parent_record unless parent_record.authorized_for?(crud_type: crud_type)
|
|
63
69
|
|
|
@@ -91,7 +97,13 @@ module ActiveScaffold
|
|
|
91
97
|
column.params.select { |p| attributes.key? p }.each { |p| parent_record.send(:"#{p}=", attributes[p]) }
|
|
92
98
|
end
|
|
93
99
|
|
|
94
|
-
def update_column_from_params(parent_record, column, attribute,
|
|
100
|
+
def update_column_from_params(parent_record, column, attribute,
|
|
101
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
102
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
103
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
104
|
+
positional_avoid_changes, avoid_changes,
|
|
105
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
106
|
+
)
|
|
95
107
|
value = column_value_from_param_value(parent_record, column, attribute, avoid_changes)
|
|
96
108
|
if column.association
|
|
97
109
|
update_column_association(parent_record, column, attribute, value, avoid_changes)
|
|
@@ -110,7 +122,13 @@ module ActiveScaffold
|
|
|
110
122
|
parent_record.send(:"#{column.association.foreign_key}=", value&.id) if column.association.belongs_to?
|
|
111
123
|
end
|
|
112
124
|
|
|
113
|
-
def update_column_association(parent_record, column, attribute, value,
|
|
125
|
+
def update_column_association(parent_record, column, attribute, value,
|
|
126
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
127
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
128
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
129
|
+
positional_avoid_changes, avoid_changes,
|
|
130
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
131
|
+
)
|
|
114
132
|
if avoid_changes
|
|
115
133
|
assign_column_association(parent_record, column, attribute, value)
|
|
116
134
|
elsif column.association.collection? && column.association.through_singular?
|
|
@@ -126,7 +144,13 @@ module ActiveScaffold
|
|
|
126
144
|
parent_record.association(column.name).target = value
|
|
127
145
|
end
|
|
128
146
|
|
|
129
|
-
def column_value_from_param_value(parent_record, column, value,
|
|
147
|
+
def column_value_from_param_value(parent_record, column, value,
|
|
148
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
149
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
150
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
151
|
+
positional_avoid_changes, avoid_changes,
|
|
152
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
153
|
+
)
|
|
130
154
|
# convert the value, possibly by instantiating associated objects
|
|
131
155
|
form_ui = column.form_ui || column.column&.type
|
|
132
156
|
if form_ui && respond_to?(:"column_value_for_#{form_ui}_type", true)
|
|
@@ -205,7 +229,13 @@ module ActiveScaffold
|
|
|
205
229
|
end
|
|
206
230
|
end
|
|
207
231
|
|
|
208
|
-
def column_value_from_param_hash_value(parent_record, column, value,
|
|
232
|
+
def column_value_from_param_hash_value(parent_record, column, value,
|
|
233
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
234
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
235
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
236
|
+
positional_avoid_changes, avoid_changes,
|
|
237
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
238
|
+
)
|
|
209
239
|
if column.association&.singular?
|
|
210
240
|
manage_nested_record_from_params(parent_record, column, value, avoid_changes)
|
|
211
241
|
elsif column.association&.collection?
|
|
@@ -233,7 +263,13 @@ module ActiveScaffold
|
|
|
233
263
|
columns ? subform_cfg.build_action_columns(columns) : subform_cfg.columns
|
|
234
264
|
end
|
|
235
265
|
|
|
236
|
-
def manage_nested_record_from_params(parent_record, column, attributes,
|
|
266
|
+
def manage_nested_record_from_params(parent_record, column, attributes,
|
|
267
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
268
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
269
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
270
|
+
positional_avoid_changes, avoid_changes,
|
|
271
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
272
|
+
)
|
|
237
273
|
return nil unless avoid_changes || build_record_from_params?(attributes, column, parent_record)
|
|
238
274
|
|
|
239
275
|
record = find_or_create_for_params(attributes, column, parent_record, avoid_changes)
|
|
@@ -259,7 +295,13 @@ module ActiveScaffold
|
|
|
259
295
|
# Attempts to create or find an instance of the klass of the association in parent_column from the
|
|
260
296
|
# request parameters given. If params[primary_key] exists it will attempt to find an existing object
|
|
261
297
|
# otherwise it will build a new one.
|
|
262
|
-
def find_or_create_for_params(params, parent_column, parent_record,
|
|
298
|
+
def find_or_create_for_params(params, parent_column, parent_record,
|
|
299
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
300
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
301
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
302
|
+
positional_avoid_changes, avoid_changes,
|
|
303
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
304
|
+
)
|
|
263
305
|
current = parent_record.send(parent_column.name)
|
|
264
306
|
klass = parent_column.association.klass(parent_record)
|
|
265
307
|
if params.key? klass.primary_key
|
|
@@ -277,7 +319,13 @@ module ActiveScaffold
|
|
|
277
319
|
|
|
278
320
|
# Attempts to find an instance of klass (which must be an ActiveRecord object) with id primary key
|
|
279
321
|
# Returns record from current if it's included or find from DB
|
|
280
|
-
def record_from_current_or_find(klass, id, current,
|
|
322
|
+
def record_from_current_or_find(klass, id, current,
|
|
323
|
+
positional_avoid_changes = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
324
|
+
avoid_changes: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
325
|
+
avoid_changes = ActiveScaffold.deprecated_positional_argument(
|
|
326
|
+
positional_avoid_changes, avoid_changes,
|
|
327
|
+
method_name: __method__, argument_name: :avoid_changes, default: false
|
|
328
|
+
)
|
|
281
329
|
record = record_from_current(current, id)
|
|
282
330
|
record ||= klass.new(klass.primary_key => id) if avoid_changes
|
|
283
331
|
record ||= klass.find(id)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module ActiveScaffold::Actions
|
|
4
4
|
module DeletedRecords
|
|
5
5
|
def self.included(base)
|
|
6
|
+
base.before_action :deleted_authorized_filter, only: :deleted
|
|
6
7
|
base.class_eval do
|
|
7
8
|
config = active_scaffold_config
|
|
8
9
|
if config.actions.include?(:nested) && config.deleted_records.nested_link_group
|
|
@@ -14,13 +15,7 @@ module ActiveScaffold::Actions
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def deleted
|
|
17
|
-
query =
|
|
18
|
-
if nested? && nested.child_association&.belongs_to? && PaperTrail::Version.respond_to?(:where_object)
|
|
19
|
-
foreign_key = nested.child_association.foreign_key
|
|
20
|
-
parent_id = nested.parent_id
|
|
21
|
-
parent_id = parent_id&.to_i if self.class.active_scaffold_config.columns[foreign_key]&.number?
|
|
22
|
-
query = query.where_object(foreign_key => parent_id)
|
|
23
|
-
end
|
|
18
|
+
query = deleted_records_query
|
|
24
19
|
pager = Paginator.new(query.count, active_scaffold_config.list.per_page) do |offset, per_page|
|
|
25
20
|
query.offset(offset).limit(per_page).map(&:reify)
|
|
26
21
|
end
|
|
@@ -29,5 +24,26 @@ module ActiveScaffold::Actions
|
|
|
29
24
|
@records = @page.items
|
|
30
25
|
respond_to_action(:list)
|
|
31
26
|
end
|
|
27
|
+
|
|
28
|
+
protected
|
|
29
|
+
|
|
30
|
+
def deleted_records_query
|
|
31
|
+
query = PaperTrail::Version.destroys.where(item_type: active_scaffold_config.model.name)
|
|
32
|
+
if nested? && nested.child_association&.belongs_to? && PaperTrail::Version.respond_to?(:where_object)
|
|
33
|
+
foreign_key = nested.child_association.foreign_key
|
|
34
|
+
parent_id = nested.parent_id
|
|
35
|
+
parent_id = parent_id&.to_i if self.class.active_scaffold_config.columns[foreign_key]&.number?
|
|
36
|
+
query = query.where_object(foreign_key => parent_id)
|
|
37
|
+
end
|
|
38
|
+
query
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def deleted_authorized?
|
|
42
|
+
list_authorized?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def deleted_authorized_filter
|
|
46
|
+
raise ActiveScaffold::ActionNotAllowed unless deleted_authorized?
|
|
47
|
+
end
|
|
32
48
|
end
|
|
33
49
|
end
|
|
@@ -163,8 +163,9 @@ module ActiveScaffold
|
|
|
163
163
|
elsif association.polymorphic?
|
|
164
164
|
apply_constraint_on_polymorphic_association(record, association, value)
|
|
165
165
|
elsif !association.source_reflection&.through? && # regular singular association, or one-level through association
|
|
166
|
-
!value.is_a?(Array)
|
|
167
|
-
|
|
166
|
+
(!value.is_a?(Array) || value.size == 1)
|
|
167
|
+
constraint_value = value.is_a?(Array) ? value.first : value
|
|
168
|
+
record.send(:"#{association.name}=", association.klass.find(constraint_value))
|
|
168
169
|
|
|
169
170
|
# setting the belongs_to side of a has_one isn't safe. if the has_one was already
|
|
170
171
|
# specified, rails won't automatically clear out the previous associated record.
|
|
@@ -4,7 +4,13 @@ module ActiveScaffold
|
|
|
4
4
|
module Helpers
|
|
5
5
|
module AssociationHelpers
|
|
6
6
|
# Cache the options for select
|
|
7
|
-
def cache_association_options(association, conditions, klass,
|
|
7
|
+
def cache_association_options(association, conditions, klass,
|
|
8
|
+
positional_cache = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
9
|
+
cache: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
10
|
+
cache = ActiveScaffold.deprecated_positional_argument(
|
|
11
|
+
positional_cache, cache,
|
|
12
|
+
method_name: __method__, argument_name: :cache, default: true
|
|
13
|
+
)
|
|
8
14
|
if active_scaffold_config.cache_association_options && cache
|
|
9
15
|
@_associations_cache ||= Hash.new { |h, k| h[k] = {} }
|
|
10
16
|
key = [association.name, association.inverse_klass.name, klass.respond_to?(:cache_key) ? klass.cache_key : klass.name].join('/')
|
|
@@ -52,7 +52,20 @@ module ActiveScaffold
|
|
|
52
52
|
handle_exception_on_column(e, column, record)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
def active_scaffold_render_subform_column(column, scope, crud_type, readonly,
|
|
55
|
+
def active_scaffold_render_subform_column(column, scope, crud_type, readonly, *positional_arguments,
|
|
56
|
+
add_class: POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
57
|
+
record: POSITIONAL_ARGUMENT_NOT_GIVEN, form_columns: nil)
|
|
58
|
+
raise ArgumentError, 'too many positional arguments' if positional_arguments.size > 2
|
|
59
|
+
|
|
60
|
+
positional_add_class = positional_arguments.fetch(0, POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
61
|
+
positional_record = positional_arguments.fetch(1, POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
62
|
+
add_class = ActiveScaffold.deprecated_positional_argument(
|
|
63
|
+
positional_add_class, add_class,
|
|
64
|
+
method_name: __method__, argument_name: :add_class, default: false
|
|
65
|
+
)
|
|
66
|
+
record = ActiveScaffold.positional_or_keyword_argument(
|
|
67
|
+
positional_record, record, argument_name: :record, default: nil
|
|
68
|
+
)
|
|
56
69
|
if add_class
|
|
57
70
|
col_class = []
|
|
58
71
|
col_class << 'required' if column.required?(action_for_validation(record))
|
|
@@ -156,7 +169,13 @@ module ActiveScaffold
|
|
|
156
169
|
url_params
|
|
157
170
|
end
|
|
158
171
|
|
|
159
|
-
def update_columns_options(column, scope, options,
|
|
172
|
+
def update_columns_options(column, scope, options,
|
|
173
|
+
positional_force = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
174
|
+
force: POSITIONAL_ARGUMENT_NOT_GIVEN, form_columns: nil, url_params: {})
|
|
175
|
+
force = ActiveScaffold.deprecated_positional_argument(
|
|
176
|
+
positional_force, force,
|
|
177
|
+
method_name: __method__, argument_name: :force, default: false
|
|
178
|
+
)
|
|
160
179
|
record = options[:object]
|
|
161
180
|
subform_controller = controller.class.active_scaffold_controller_for(record.class) if scope
|
|
162
181
|
form_columns ||= current_form_columns(record, scope, subform_controller)
|
|
@@ -249,7 +268,20 @@ module ActiveScaffold
|
|
|
249
268
|
as_element(:form_field_description, h(desc) + as_element(:form_field_description_close)) if desc.present?
|
|
250
269
|
end
|
|
251
270
|
|
|
252
|
-
def form_attribute(column, record, scope = nil,
|
|
271
|
+
def form_attribute(column, record, scope = nil, *positional_arguments,
|
|
272
|
+
only_value: POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
273
|
+
col_class: POSITIONAL_ARGUMENT_NOT_GIVEN, form_columns: nil, field: nil)
|
|
274
|
+
raise ArgumentError, 'too many positional arguments' if positional_arguments.size > 2
|
|
275
|
+
|
|
276
|
+
positional_only_value = positional_arguments.fetch(0, POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
277
|
+
positional_col_class = positional_arguments.fetch(1, POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
278
|
+
only_value = ActiveScaffold.deprecated_positional_argument(
|
|
279
|
+
positional_only_value, only_value,
|
|
280
|
+
method_name: __method__, argument_name: :only_value, default: false
|
|
281
|
+
)
|
|
282
|
+
col_class = ActiveScaffold.positional_or_keyword_argument(
|
|
283
|
+
positional_col_class, col_class, argument_name: :col_class, default: nil
|
|
284
|
+
)
|
|
253
285
|
column_options = active_scaffold_input_options(column, scope, object: record)
|
|
254
286
|
collapsible_id = column_options.delete :collapsible_id
|
|
255
287
|
attributes = field_attributes(column, record)
|
|
@@ -293,14 +325,26 @@ module ActiveScaffold
|
|
|
293
325
|
column.label unless hidden
|
|
294
326
|
end
|
|
295
327
|
|
|
296
|
-
def form_hidden_attribute(column, record, scope = nil,
|
|
328
|
+
def form_hidden_attribute(column, record, scope = nil,
|
|
329
|
+
positional_clear = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
330
|
+
clear: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
331
|
+
clear = ActiveScaffold.deprecated_positional_argument(
|
|
332
|
+
positional_clear, clear,
|
|
333
|
+
method_name: __method__, argument_name: :clear, default: false
|
|
334
|
+
)
|
|
297
335
|
content_tag :dl, style: 'display: none' do
|
|
298
336
|
content_tag(:dt, '') <<
|
|
299
337
|
content_tag(:dd, form_hidden_field(column, record, scope, clear))
|
|
300
338
|
end
|
|
301
339
|
end
|
|
302
340
|
|
|
303
|
-
def form_hidden_field(column, record, scope,
|
|
341
|
+
def form_hidden_field(column, record, scope,
|
|
342
|
+
positional_clear = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
343
|
+
clear: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
344
|
+
clear = ActiveScaffold.deprecated_positional_argument(
|
|
345
|
+
positional_clear, clear,
|
|
346
|
+
method_name: __method__, argument_name: :clear, default: false
|
|
347
|
+
)
|
|
304
348
|
options = active_scaffold_input_options(column, scope)
|
|
305
349
|
value = record.send(column.name) unless clear
|
|
306
350
|
if column.association&.collection?
|
|
@@ -93,7 +93,7 @@ module ActiveScaffold
|
|
|
93
93
|
associated.collect!(&:to_i)
|
|
94
94
|
method = ui_options[:label_method] || :to_label
|
|
95
95
|
helper_method = association_helper_method(column.association, :sorted_association_options_find)
|
|
96
|
-
select_options = send(helper_method, column.association,
|
|
96
|
+
select_options = send(helper_method, column.association, {}, record).collect do |r|
|
|
97
97
|
[r.send(method), r.id]
|
|
98
98
|
end
|
|
99
99
|
else
|
|
@@ -119,7 +119,7 @@ module ActiveScaffold
|
|
|
119
119
|
associated = associated.is_a?(Array) ? associated.map(&:to_i) : associated.to_i unless associated.nil?
|
|
120
120
|
method = column.association.belongs_to? ? column.association.foreign_key : column.name
|
|
121
121
|
helper_method = association_helper_method(column.association, :sorted_association_options_find)
|
|
122
|
-
select_options = send(helper_method, column.association,
|
|
122
|
+
select_options = send(helper_method, column.association, {}, record)
|
|
123
123
|
else
|
|
124
124
|
method = column.name
|
|
125
125
|
select_options = active_scaffold_translated_enum_options(column, record, ui_options: ui_options)
|
|
@@ -57,7 +57,12 @@ module ActiveScaffold
|
|
|
57
57
|
|
|
58
58
|
# This is the template finder logic, keep it updated with however we find stuff in rails
|
|
59
59
|
# currently this very similar to the logic in ActionBase::Base.render for options file
|
|
60
|
-
def template_exists?(template_name,
|
|
60
|
+
def template_exists?(template_name, positional_partial = POSITIONAL_ARGUMENT_NOT_GIVEN,
|
|
61
|
+
partial: POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
62
|
+
partial = ActiveScaffold.deprecated_positional_argument(
|
|
63
|
+
positional_partial, partial,
|
|
64
|
+
method_name: __method__, argument_name: :partial, default: false
|
|
65
|
+
)
|
|
61
66
|
if @_view_paths
|
|
62
67
|
restore_view_paths = lookup_context.view_paths
|
|
63
68
|
lookup_context.view_paths = @_view_paths
|
data/lib/active_scaffold.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveScaffold
|
|
4
|
+
POSITIONAL_ARGUMENT_NOT_GIVEN = Object.new.freeze
|
|
5
|
+
|
|
4
6
|
autoload :ActiveRecordPermissions, 'active_scaffold/active_record_permissions'
|
|
5
7
|
autoload :Assets, 'active_scaffold/assets'
|
|
6
8
|
autoload :AttributeParams, 'active_scaffold/attribute_params'
|
|
@@ -260,7 +262,33 @@ module ActiveScaffold
|
|
|
260
262
|
end
|
|
261
263
|
|
|
262
264
|
def self.deprecator
|
|
263
|
-
@deprecator ||= ActiveSupport::Deprecation.new('4.
|
|
265
|
+
@deprecator ||= ActiveSupport::Deprecation.new('4.5', 'ActiveScaffold')
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def self.deprecated_positional_argument(positional, keyword, method_name:, argument_name:, default:)
|
|
269
|
+
if positional.equal?(POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
270
|
+
keyword.equal?(POSITIONAL_ARGUMENT_NOT_GIVEN) ? default : keyword
|
|
271
|
+
elsif keyword.equal?(POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
272
|
+
deprecator.warn(
|
|
273
|
+
"Passing `#{argument_name}` positionally to `#{method_name}` is deprecated; " \
|
|
274
|
+
"use `#{argument_name}:` instead. Positional support will be removed in ActiveScaffold 4.5. " \
|
|
275
|
+
'Overrides must accept both forms during 4.4 and pass the argument to `super` as a keyword. ' \
|
|
276
|
+
'See https://github.com/activescaffold/active_scaffold/blob/4-4-stable/CHANGELOG.rdoc'
|
|
277
|
+
)
|
|
278
|
+
positional
|
|
279
|
+
else
|
|
280
|
+
raise ArgumentError, "#{argument_name} was given both positionally and as a keyword"
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def self.positional_or_keyword_argument(positional, keyword, argument_name:, default:)
|
|
285
|
+
if positional.equal?(POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
286
|
+
keyword.equal?(POSITIONAL_ARGUMENT_NOT_GIVEN) ? default : keyword
|
|
287
|
+
elsif keyword.equal?(POSITIONAL_ARGUMENT_NOT_GIVEN)
|
|
288
|
+
positional
|
|
289
|
+
else
|
|
290
|
+
raise ArgumentError, "#{argument_name} was given both positionally and as a keyword"
|
|
291
|
+
end
|
|
264
292
|
end
|
|
265
293
|
|
|
266
294
|
def self.log_exception(exception, message)
|