active_scaffold 3.6.9 → 3.6.11.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1e1f178ccfe11c704e5064d0ee50bfa6a27d6aee4f478f478e6e0529a7e0683
4
- data.tar.gz: de3fb5ad387969bc8c796ca9db23de2f311e8b16f6002316456b475953d66ae1
3
+ metadata.gz: 10795ad02dbbf1ea2033af6b1b36857f0105acf45daa21f44bf576737b838331
4
+ data.tar.gz: e5fb0e9f651127a06d8057a5eeab6934ba62211c9bb9d3f0b8ac6df5e7e5bb58
5
5
  SHA512:
6
- metadata.gz: 175f49bcb07a4fd3fd313f5437b3d2b438a20d9a697e2cc481fcc7086a4a0add3e08fa342ed90f984fed13eff68bad632b8bd772bbbf6869319d1024ace9082d
7
- data.tar.gz: 8db9c02a65266fc858910ecf180800c4adabe0913eb02cb3464db665f51ad3ab3230a5bc1e6d38a581d93a874d390e6e8fa7ae7f72ec5c09d54cbecfcb070a71
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 = clonedNodes.after(patternNode);
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(editField, textValue) {
353
- var function_name = 'setValueFor' + editField.get(0).nodeName.toLowerCase();
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](editField, textValue);
358
+ this[function_name](editFields, textValue);
356
359
  } else {
357
360
  editField.val(textValue);
358
361
  }
359
362
  },
360
363
 
361
- setValueForselect: function(editField, textValue) {
362
- var option_value = editField.children("option:contains('" + textValue + "')").val();
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 => @records.map(&key.to_sym))
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 => @records.map(&:id))
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': @records.map(&:id)}}
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
- @record = get_row
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
- self.required = active_record_class.validators_on(name).any? do |val|
357
- validator_force_required?(val)
358
- end
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
- true
445
+ validator_required_on(val)
440
446
  when ActiveModel::Validations::InclusionValidator
441
- !val.options[:allow_nil] && !val.options[:allow_blank] &&
442
- !inclusion_validator_for_checkbox?(val)
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) && v.attributes.include?(column.name)
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}#numerical_constarints") do
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)
@@ -2,7 +2,7 @@ module ActiveScaffold
2
2
  module Version
3
3
  MAJOR = 3
4
4
  MINOR = 6
5
- PATCH = 9
5
+ PATCH = '11.1'.freeze
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
@@ -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.9
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-05-03 00:00:00.000000000 Z
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.3.7
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