active_scaffold 3.6.9 → 3.6.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +15 -0
- data/app/assets/javascripts/jquery/jquery.editinplace.js +21 -7
- data/app/views/active_scaffold_overrides/_form.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_form_association.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +2 -2
- data/app/views/active_scaffold_overrides/_search.html.erb +1 -1
- data/lib/active_scaffold/actions/list.rb +13 -13
- data/lib/active_scaffold/actions/update.rb +1 -1
- data/lib/active_scaffold/data_structures/column.rb +19 -8
- data/lib/active_scaffold/helpers/form_column_helpers.rb +10 -4
- data/lib/active_scaffold/version.rb +1 -1
- data/test/data_structures/validation_reflection_test.rb +10 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10795ad02dbbf1ea2033af6b1b36857f0105acf45daa21f44bf576737b838331
|
4
|
+
data.tar.gz: e5fb0e9f651127a06d8057a5eeab6934ba62211c9bb9d3f0b8ac6df5e7e5bb58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e738f18a2fe367d7796057fe2f098c6bc5f7291615e4315a78a33f0283df30b7c6c12b26af51b03489112ecd2c2310ac30a5bfac7d29e1c6be26a9700982dc41
|
7
|
+
data.tar.gz: 4ccb202176df05c3f9d4882ccd4abf6f025204ffa993b9daa6c3b3b4bcabc06eb22e4f98630253a85c1ef9ce68160b11d6beeb6c6a64ae8f7a885b26e12278ed
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
= 3.6.11.1
|
2
|
+
- Fix required attribute broken on previous version when no validation was found
|
3
|
+
|
4
|
+
= 3.6.11
|
5
|
+
- Fix inplace edit cloning with jquery >= 1.9, when more than one child is cloned
|
6
|
+
- Support inplace edit cloning for :radio form_ui
|
7
|
+
- Add records parameter to cache_columns_count and related methods (count_query_for_column, mongoid_count_for_column)
|
8
|
+
- Fix required attribute when validator uses :on option, so on: :update only set required on update form, and :create only set required on create form
|
9
|
+
|
10
|
+
= 3.6.10
|
11
|
+
- Don't add numerical constraints based on conditional validation
|
12
|
+
- Fix typo in cache key for numerical constraints
|
13
|
+
- Fix duplicated params in search form, e.g. embedded constraints
|
14
|
+
|
15
|
+
= 3.6.9
|
1
16
|
- Support depend on .rb or .json locale files for date picker bridge
|
2
17
|
- Fix search with dates entered with timezone in datepicker
|
3
18
|
|
@@ -317,7 +317,6 @@ $.extend(InlineEditor.prototype, {
|
|
317
317
|
if (editorNode.data('id')) editorNode.attr('id', editorNode.data('id') + this.settings.clone_id_suffix);
|
318
318
|
editorNode.attr('name', 'inplace_value');
|
319
319
|
editorNode.addClass('editor_field');
|
320
|
-
this.setValue(editorNode, this.originalValue);
|
321
320
|
clonedNodes = editorNode;
|
322
321
|
|
323
322
|
if (patternNodes.additionalNodes) {
|
@@ -326,9 +325,10 @@ $.extend(InlineEditor.prototype, {
|
|
326
325
|
if (patternNode.data('id')) {
|
327
326
|
patternNode.attr('id', patternNode.data('id') + this.settings.clone_id_suffix);
|
328
327
|
}
|
329
|
-
clonedNodes
|
328
|
+
clonedNodes.push(patternNode[0]);
|
330
329
|
});
|
331
330
|
}
|
331
|
+
this.setValue(clonedNodes, this.originalValue);
|
332
332
|
return clonedNodes;
|
333
333
|
},
|
334
334
|
|
@@ -349,23 +349,37 @@ $.extend(InlineEditor.prototype, {
|
|
349
349
|
return nodes;
|
350
350
|
},
|
351
351
|
|
352
|
-
setValue: function(
|
353
|
-
var
|
352
|
+
setValue: function(editFields, textValue) {
|
353
|
+
var editField = editFields.find(':input').addBack(':input'),
|
354
|
+
type = editField.get(0).nodeName.toLowerCase();
|
355
|
+
if (type === 'input') type = editField.attr('type').toLowerCase();
|
356
|
+
var function_name = 'setValueFor' + type;
|
354
357
|
if (typeof(this[function_name]) == 'function') {
|
355
|
-
this[function_name](
|
358
|
+
this[function_name](editFields, textValue);
|
356
359
|
} else {
|
357
360
|
editField.val(textValue);
|
358
361
|
}
|
359
362
|
},
|
360
363
|
|
361
|
-
setValueForselect: function(
|
362
|
-
var
|
364
|
+
setValueForselect: function(editFields, textValue) {
|
365
|
+
var editField = editFields.find('select').addBack('select').first(),
|
366
|
+
option_value = editField.children("option:contains('" + textValue + "')").val();
|
363
367
|
|
364
368
|
if (typeof(option_value) !== 'undefined') {
|
365
369
|
editField.val(option_value);
|
366
370
|
}
|
367
371
|
},
|
368
372
|
|
373
|
+
setValueForradio: function(editFields, textValue) {
|
374
|
+
var editField = editFields.find('input[type=radio]').addBack('input[type=radio]').filter(function() {
|
375
|
+
var contains = ':contains("' + textValue + '")';
|
376
|
+
return editFields.find('label[for="' + $(this).attr('id') + '"]' + contains).length ||
|
377
|
+
$(this).closest('label' + contains).length;
|
378
|
+
}).first();
|
379
|
+
|
380
|
+
if (editField.length) editField.prop('checked', true);
|
381
|
+
},
|
382
|
+
|
369
383
|
inputNameAndClass: function() {
|
370
384
|
return ' name="inplace_value" class="inplace_field" ';
|
371
385
|
},
|
@@ -24,7 +24,7 @@
|
|
24
24
|
<%= render_column(column, @record, renders_as, scope) %>
|
25
25
|
<% end %>
|
26
26
|
<% else -%>
|
27
|
-
<li class="form-element <%= 'required' if column.required? %> <%= column.form_ui %> <%= column_css_class %>">
|
27
|
+
<li class="form-element <%= 'required' if column.required?(action_for_validation?(@record)) %> <%= column.form_ui %> <%= column_css_class %>">
|
28
28
|
<%= render_column(column, @record, renders_as, scope, !authorized) %>
|
29
29
|
</li>
|
30
30
|
<% end -%>
|
@@ -4,7 +4,7 @@ if column.show_blank_record?(associated)
|
|
4
4
|
show_blank_record = build_associated(column.association, parent_record)
|
5
5
|
end
|
6
6
|
disable_required_for_new = @disable_required_for_new
|
7
|
-
@disable_required_for_new = !!show_blank_record unless (column.association.singular? && column.required?)
|
7
|
+
@disable_required_for_new = !!show_blank_record unless (column.association.singular? && column.required?(action_for_validation?(parent_record)))
|
8
8
|
subform_div_id = "#{sub_form_id(:association => column.name, :id => parent_record.id || generated_id(parent_record) || 99999999999)}-div"
|
9
9
|
|
10
10
|
# render footer before rendering associated records, fixes create new on self-associations
|
@@ -58,7 +58,7 @@
|
|
58
58
|
end
|
59
59
|
|
60
60
|
col_class = default_col_class.clone
|
61
|
-
col_class << 'required' if column.required?
|
61
|
+
col_class << 'required' if column.required?(action_for_validation?(record))
|
62
62
|
col_class << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc)
|
63
63
|
col_class << 'hidden' if column_renders_as(column) == :hidden
|
64
64
|
-%>
|
@@ -88,7 +88,7 @@
|
|
88
88
|
<% columns_group.each_column(for: record.class, crud_type: :read, flatten: true) do |col| %>
|
89
89
|
<%
|
90
90
|
col_class = default_col_class.clone
|
91
|
-
col_class << 'required' if col.required?
|
91
|
+
col_class << 'required' if col.required?(action_for_validation?(record))
|
92
92
|
col_class << col.css_class unless col.css_class.nil? || col.css_class.is_a?(Proc)
|
93
93
|
col_class << 'hidden' if column_renders_as(col) == :hidden
|
94
94
|
%>
|
@@ -14,7 +14,7 @@
|
|
14
14
|
hidden_params = url_options.except(:controller, :action, :id, :search).to_query.split(Rack::Utils::DEFAULT_SEP)
|
15
15
|
-%>
|
16
16
|
|
17
|
-
<%= form_tag url_options, options do %>
|
17
|
+
<%= form_tag url_options.slice(:controller, :action, :id, :search), options do %>
|
18
18
|
<% hidden_params.each do |pair| -%>
|
19
19
|
<% key, value = pair.split('=', 2).map { |str| Rack::Utils.unescape(str) } -%>
|
20
20
|
<%= hidden_field_tag(key, value) %>
|
@@ -125,7 +125,7 @@ module ActiveScaffold::Actions
|
|
125
125
|
@remove_id_from_list_links = params[:id].blank?
|
126
126
|
@page = current_page
|
127
127
|
@records = @page.items
|
128
|
-
cache_column_counts
|
128
|
+
cache_column_counts @records
|
129
129
|
end
|
130
130
|
|
131
131
|
def columns_to_cache_counts
|
@@ -136,12 +136,12 @@ module ActiveScaffold::Actions
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
def cache_column_counts
|
139
|
+
def cache_column_counts(records)
|
140
140
|
@counts = columns_to_cache_counts.each_with_object({}) do |column, counts|
|
141
141
|
if ActiveScaffold::OrmChecks.active_record?(column.association.klass)
|
142
|
-
counts[column.name] = count_query_for_column(column).count
|
142
|
+
counts[column.name] = count_query_for_column(column, records).count
|
143
143
|
elsif ActiveScaffold::OrmChecks.mongoid?(column.association.klass)
|
144
|
-
counts[column.name] = mongoid_count_for_column(column)
|
144
|
+
counts[column.name] = mongoid_count_for_column(column, records)
|
145
145
|
end
|
146
146
|
end
|
147
147
|
end
|
@@ -151,17 +151,17 @@ module ActiveScaffold::Actions
|
|
151
151
|
(!column.association.as || column.association.reverse_association)
|
152
152
|
end
|
153
153
|
|
154
|
-
def count_query_for_column(column)
|
154
|
+
def count_query_for_column(column, records)
|
155
155
|
if count_on_association_class?(column)
|
156
|
-
count_query_on_association_class(column)
|
156
|
+
count_query_on_association_class(column, records)
|
157
157
|
else
|
158
|
-
count_query_with_join(column)
|
158
|
+
count_query_with_join(column, records)
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
-
def count_query_on_association_class(column)
|
162
|
+
def count_query_on_association_class(column, records)
|
163
163
|
key = column.association.primary_key || :id
|
164
|
-
query = column.association.klass.where(column.association.foreign_key =>
|
164
|
+
query = column.association.klass.where(column.association.foreign_key => records.map(&key.to_sym))
|
165
165
|
if column.association.as
|
166
166
|
query.where!(column.association.reverse_association.foreign_type => active_scaffold_config.model.name)
|
167
167
|
end
|
@@ -171,17 +171,17 @@ module ActiveScaffold::Actions
|
|
171
171
|
query.group(column.association.foreign_key)
|
172
172
|
end
|
173
173
|
|
174
|
-
def count_query_with_join(column)
|
174
|
+
def count_query_with_join(column, records)
|
175
175
|
klass = column.association.klass
|
176
|
-
query = active_scaffold_config.model.where(active_scaffold_config.primary_key =>
|
176
|
+
query = active_scaffold_config.model.where(active_scaffold_config.primary_key => records.map(&:id))
|
177
177
|
.joins(column.name).group(active_scaffold_config.primary_key)
|
178
178
|
.select("#{klass.quoted_table_name}.#{klass.quoted_primary_key}")
|
179
179
|
query = query.uniq if column.association.scope && klass.instance_exec(&column.association.scope).values[:distinct]
|
180
180
|
query
|
181
181
|
end
|
182
182
|
|
183
|
-
def mongoid_count_for_column(column)
|
184
|
-
matches = {column.association.foreign_key => {'$in':
|
183
|
+
def mongoid_count_for_column(column, records)
|
184
|
+
matches = {column.association.foreign_key => {'$in': records.map(&:id)}}
|
185
185
|
if column.association.as
|
186
186
|
matches[column.association.reverse_association.foreign_type] = {'$eq': active_scaffold_config.model.name}
|
187
187
|
end
|
@@ -69,7 +69,7 @@ module ActiveScaffold::Actions
|
|
69
69
|
@updated_record = @record
|
70
70
|
# get_row so associations are cached like in list action
|
71
71
|
# if record doesn't fullfil current conditions remove it from list
|
72
|
-
|
72
|
+
get_row
|
73
73
|
rescue ActiveRecord::RecordNotFound
|
74
74
|
nil
|
75
75
|
end
|
@@ -66,8 +66,12 @@ module ActiveScaffold::DataStructures
|
|
66
66
|
# whether the field is required or not. used on the form for visually indicating the fact to the user.
|
67
67
|
# TODO: move into predicate
|
68
68
|
attr_writer :required
|
69
|
-
def required?
|
70
|
-
@required
|
69
|
+
def required?(action = nil)
|
70
|
+
if action && @required
|
71
|
+
@required == true || @required.include?(action)
|
72
|
+
else
|
73
|
+
@required
|
74
|
+
end
|
71
75
|
end
|
72
76
|
|
73
77
|
attr_reader :update_columns
|
@@ -353,9 +357,11 @@ module ActiveScaffold::DataStructures
|
|
353
357
|
|
354
358
|
# default all the configurable variables
|
355
359
|
self.css_class = ''
|
356
|
-
|
357
|
-
|
358
|
-
|
360
|
+
validators_force_require_on = active_record_class.validators_on(name)
|
361
|
+
.map { |val| validator_force_required?(val) }
|
362
|
+
.select(&:present?)
|
363
|
+
self.required = validators_force_require_on.any? { |opt| opt == true } ||
|
364
|
+
validators_force_require_on.reject { |opt| opt == true }.flatten.presence
|
359
365
|
self.sort = true
|
360
366
|
self.search_sql = true
|
361
367
|
|
@@ -436,13 +442,18 @@ module ActiveScaffold::DataStructures
|
|
436
442
|
return false if val.options[:if] || val.options[:unless]
|
437
443
|
case val
|
438
444
|
when ActiveModel::Validations::PresenceValidator
|
439
|
-
|
445
|
+
validator_required_on(val)
|
440
446
|
when ActiveModel::Validations::InclusionValidator
|
441
|
-
!val.options[:allow_nil] && !val.options[:allow_blank] &&
|
442
|
-
|
447
|
+
if !val.options[:allow_nil] && !val.options[:allow_blank] && !inclusion_validator_for_checkbox?(val)
|
448
|
+
validator_required_on(val)
|
449
|
+
end
|
443
450
|
end
|
444
451
|
end
|
445
452
|
|
453
|
+
def validator_required_on(val)
|
454
|
+
val.options[:on] ? Array(val.options[:on]) : true
|
455
|
+
end
|
456
|
+
|
446
457
|
def inclusion_validator_for_checkbox?(val)
|
447
458
|
@form_ui == :checkbox &&
|
448
459
|
[[true, false], [false, true]].include?(val.options[:with] || val.options[:within] || val.options[:in])
|
@@ -55,7 +55,7 @@ module ActiveScaffold
|
|
55
55
|
def active_scaffold_render_subform_column(column, scope, crud_type, readonly, add_class = false, record = nil) # rubocop:disable Metrics/ParameterLists
|
56
56
|
if add_class
|
57
57
|
col_class = []
|
58
|
-
col_class << 'required' if column.required?
|
58
|
+
col_class << 'required' if column.required?(action_for_validation?(record))
|
59
59
|
col_class << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc)
|
60
60
|
col_class << 'hidden' if column_renders_as(column) == :hidden
|
61
61
|
col_class << 'checkbox' if column.form_ui == :checkbox
|
@@ -85,13 +85,17 @@ module ActiveScaffold
|
|
85
85
|
options
|
86
86
|
end
|
87
87
|
|
88
|
+
def action_for_validation?(record)
|
89
|
+
record&.persisted? ? :update : :create
|
90
|
+
end
|
91
|
+
|
88
92
|
# the standard active scaffold options used for class, name and scope
|
89
93
|
def active_scaffold_input_options(column, scope = nil, options = {})
|
90
94
|
name = scope ? "record#{scope}[#{column.name}]" : "record[#{column.name}]"
|
91
95
|
record = options[:object]
|
92
96
|
|
93
97
|
# Add some HTML5 attributes for in-browser validation and better user experience
|
94
|
-
if column.required? && (!@disable_required_for_new || scope.nil? || record&.persisted?)
|
98
|
+
if column.required?(action_for_validation?(record)) && (!@disable_required_for_new || scope.nil? || record&.persisted?)
|
95
99
|
options[:required] = true
|
96
100
|
end
|
97
101
|
options[:placeholder] = column.placeholder if column.placeholder.present?
|
@@ -720,7 +724,9 @@ module ActiveScaffold
|
|
720
724
|
# Try to get numerical constraints from model's validators
|
721
725
|
def column_numerical_constraints(column, options)
|
722
726
|
validators = column.active_record_class.validators.select do |v|
|
723
|
-
v.is_a?(ActiveModel::Validations::NumericalityValidator) &&
|
727
|
+
v.is_a?(ActiveModel::Validations::NumericalityValidator) &&
|
728
|
+
v.attributes.include?(column.name) &&
|
729
|
+
!v.options[:if] && !v.options[:unless]
|
724
730
|
end
|
725
731
|
|
726
732
|
equal_validator = validators.find { |v| v.options[:equal_to] }
|
@@ -770,7 +776,7 @@ module ActiveScaffold
|
|
770
776
|
end
|
771
777
|
|
772
778
|
def numerical_constraints_for_column(column, options)
|
773
|
-
constraints = Rails.cache.fetch("#{column.cache_key}#
|
779
|
+
constraints = Rails.cache.fetch("#{column.cache_key}#numerical_constraints") do
|
774
780
|
column_numerical_constraints(column, options)
|
775
781
|
end
|
776
782
|
constraints.merge(options)
|
@@ -9,6 +9,16 @@ class ValidationReflectionTest < MiniTest::Test
|
|
9
9
|
assert column.required?
|
10
10
|
end
|
11
11
|
|
12
|
+
def test_set_required_for_validates_presence_of_with_on
|
13
|
+
column = ActiveScaffold::DataStructures::Column.new(:name, Company)
|
14
|
+
refute column.required?
|
15
|
+
Company.expects(:validators_on).with(:name).returns([ActiveModel::Validations::PresenceValidator.new(:attributes => :name, :on => [:create])])
|
16
|
+
column = ActiveScaffold::DataStructures::Column.new(:name, Company)
|
17
|
+
assert column.required?
|
18
|
+
assert column.required?(:create)
|
19
|
+
refute column.required?(:update)
|
20
|
+
end
|
21
|
+
|
12
22
|
def test_set_required_for_validates_inclusion_of
|
13
23
|
column = ActiveScaffold::DataStructures::Column.new(:name, Company)
|
14
24
|
refute column.required?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_scaffold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.6.
|
4
|
+
version: 3.6.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Many, see README
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -477,7 +477,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
477
477
|
- !ruby/object:Gem::Version
|
478
478
|
version: '0'
|
479
479
|
requirements: []
|
480
|
-
rubygems_version: 3.
|
480
|
+
rubygems_version: 3.0.9
|
481
481
|
signing_key:
|
482
482
|
specification_version: 4
|
483
483
|
summary: Rails 4.x and 5.x versions of ActiveScaffold supporting prototype and jquery
|