active_scaffold 3.6.0.rc1 → 3.6.2

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +26 -0
  3. data/README.md +10 -9
  4. data/app/assets/javascripts/jquery/active_scaffold.js +48 -14
  5. data/app/assets/stylesheets/active_scaffold_layout.css +1 -1
  6. data/app/views/active_scaffold_overrides/_form_association.html.erb +2 -1
  7. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +22 -6
  8. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +3 -3
  9. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
  10. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +2 -2
  11. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  12. data/lib/active_scaffold/actions/core.rb +5 -2
  13. data/lib/active_scaffold/actions/list.rb +1 -1
  14. data/lib/active_scaffold/actions/nested.rb +1 -1
  15. data/lib/active_scaffold/actions/subform.rb +12 -6
  16. data/lib/active_scaffold/attribute_params.rb +6 -16
  17. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +1 -0
  18. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +4 -4
  19. data/lib/active_scaffold/bridges/bitfields.rb +1 -1
  20. data/lib/active_scaffold/bridges/bitfields/list_ui.rb +19 -0
  21. data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
  22. data/lib/active_scaffold/bridges/record_select/helpers.rb +3 -1
  23. data/lib/active_scaffold/config/list.rb +1 -1
  24. data/lib/active_scaffold/data_structures/action_columns.rb +1 -1
  25. data/lib/active_scaffold/data_structures/association/abstract.rb +1 -4
  26. data/lib/active_scaffold/data_structures/nested_info.rb +14 -2
  27. data/lib/active_scaffold/extensions/action_view_rendering.rb +66 -25
  28. data/lib/active_scaffold/extensions/localize.rb +1 -1
  29. data/lib/active_scaffold/finder.rb +7 -5
  30. data/lib/active_scaffold/helpers/controller_helpers.rb +11 -0
  31. data/lib/active_scaffold/helpers/form_column_helpers.rb +52 -15
  32. data/lib/active_scaffold/helpers/list_column_helpers.rb +10 -6
  33. data/lib/active_scaffold/helpers/search_column_helpers.rb +14 -7
  34. data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
  35. data/lib/active_scaffold/tableless.rb +16 -2
  36. data/lib/active_scaffold/version.rb +1 -1
  37. data/lib/generators/active_scaffold/install_generator.rb +51 -3
  38. data/test/data_structures/action_columns_test.rb +1 -1
  39. data/test/extensions/action_view_rendering_test.rb +20 -0
  40. data/test/misc/constraints_test.rb +1 -1
  41. data/test/misc/tableless_test.rb +8 -0
  42. data/test/mock_app/app/controllers/people_controller.rb +2 -0
  43. data/test/mock_app/app/controllers/roles_controller.rb +4 -0
  44. data/test/mock_app/app/views/active_scaffold_overrides/_form.html.erb +2 -0
  45. data/test/mock_app/app/views/active_scaffold_overrides/list.html.erb +2 -0
  46. data/test/mock_app/app/views/people/_first_name_form_column.html.erb +2 -0
  47. data/test/mock_app/app/views/people/_form.html.erb +2 -0
  48. data/test/mock_app/app/views/people/list.html.erb +2 -0
  49. data/test/test_helper.rb +2 -2
  50. metadata +25 -4
@@ -1,6 +1,6 @@
1
1
  class ActiveScaffold::Bridges::Bitfields < ActiveScaffold::DataStructures::Bridge
2
2
  def self.install
3
- require File.join(File.dirname(__FILE__), 'bitfields/bitfields_bridge')
3
+ Dir[File.join(__dir__, 'bitfields', '*.rb')].each { |file| require file }
4
4
  ActiveScaffold::Config::Core.send :prepend, ActiveScaffold::Bridges::Bitfields::BitfieldsBridge
5
5
  ActiveScaffold::Config::Core.after_config_callbacks << :_setup_bitfields
6
6
  end
@@ -0,0 +1,19 @@
1
+ module ActiveScaffold
2
+ module Bridges
3
+ class Bitfields
4
+ module ListColumnHelpers
5
+ def format_column_value(record, column, value = nil)
6
+ if record.class.respond_to?(:bitfields) && record.class.bitfields&.include?(column.name)
7
+ value = record.bitfield_values(column.name).select { |_, v| v }.keys
8
+ safe_join active_scaffold_config.columns.select { |c| c.name.in? value }.map(&:label), ', '
9
+ else
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ ActionView::Base.class_eval do
18
+ include ActiveScaffold::Bridges::Bitfields::ListColumnHelpers
19
+ end
@@ -11,7 +11,9 @@ module ActiveScaffold::Actions
11
11
 
12
12
  def deleted
13
13
  query = PaperTrail::Version.destroys.where(:item_type => active_scaffold_config.model)
14
- query = query.where_object(nested.child_association.foreign_key => nested.parent_id) if nested? && nested.child_association.belongs_to? && PaperTrail::Version.respond_to?(:where_object)
14
+ if nested? && nested.child_association&.belongs_to? && PaperTrail::Version.respond_to?(:where_object)
15
+ query = query.where_object(nested.child_association.foreign_key => nested.parent_id)
16
+ end
15
17
  pager = Paginator.new(query.count, active_scaffold_config.list.per_page) do |offset, per_page|
16
18
  query.offset(offset).limit(per_page).map(&:reify)
17
19
  end
@@ -14,7 +14,9 @@ class ActiveScaffold::Bridges::RecordSelect
14
14
  record = options.delete(:object)
15
15
  if column.association&.singular?
16
16
  multiple = column.options.dig(:html_options, :multiple)
17
- active_scaffold_record_select(record, column, options, record.send(column.name), multiple)
17
+ html = active_scaffold_record_select(record, column, options, record.send(column.name), multiple)
18
+ html << active_scaffold_new_record_subform(column, record, options) if column.options[:add_new]
19
+ html
18
20
  elsif column.association&.collection?
19
21
  active_scaffold_record_select(record, column, options, record.send(column.name), true)
20
22
  else
@@ -292,7 +292,7 @@ module ActiveScaffold::Config
292
292
  @_sorting = sorting
293
293
  else
294
294
  @_sorting = default_sorting
295
- @_sorting.set(@sorting) if @sorting
295
+ @_sorting.set(*@sorting) if @sorting
296
296
  if @conf.columns.constraint_columns.present?
297
297
  @_sorting.constraint_columns = @conf.columns.constraint_columns
298
298
  end
@@ -124,7 +124,7 @@ module ActiveScaffold::DataStructures
124
124
  end
125
125
 
126
126
  def action_name
127
- @action.class.name.demodulize.underscore
127
+ @action.user_settings_key
128
128
  end
129
129
 
130
130
  def columns_key
@@ -12,13 +12,10 @@ module ActiveScaffold::DataStructures::Association
12
12
 
13
13
  def klass(record = nil)
14
14
  if polymorphic?
15
- record&.send(foreign_type)&.constantize
15
+ record&.send(foreign_type)&.safe_constantize
16
16
  else
17
17
  @association.klass
18
18
  end
19
- rescue NameError => e
20
- Rails.logger.warn "#{e.message}\n#{e.backtrace.join("\n")}"
21
- nil
22
19
  end
23
20
 
24
21
  def belongs_to?
@@ -66,6 +66,10 @@ module ActiveScaffold::DataStructures
66
66
  def sorted?(*)
67
67
  false
68
68
  end
69
+
70
+ def match_model?(model)
71
+ false
72
+ end
69
73
  end
70
74
 
71
75
  class NestedInfoAssociation < NestedInfo
@@ -100,6 +104,14 @@ module ActiveScaffold::DataStructures
100
104
  association.through?
101
105
  end
102
106
 
107
+ def match_model?(model)
108
+ if association.polymorphic?
109
+ child_association&.inverse_klass == model
110
+ else
111
+ association.klass == model
112
+ end
113
+ end
114
+
103
115
  def sorted?(chain)
104
116
  default_sorting(chain).present?
105
117
  end
@@ -119,8 +131,8 @@ module ActiveScaffold::DataStructures
119
131
  protected
120
132
 
121
133
  def setup_constrained_fields
122
- @constrained_fields = Array(association.foreign_key).map(&:to_sym) unless association.belongs_to?
123
- @constrained_fields ||= []
134
+ @constrained_fields = [] if association.belongs_to? || association.through?
135
+ @constrained_fields ||= Array(association.foreign_key).map(&:to_sym)
124
136
  return unless child_association && child_association != association
125
137
 
126
138
  @constrained_fields << child_association.name
@@ -45,31 +45,7 @@ module ActiveScaffold #:nodoc:
45
45
  @_view_paths ||= lookup_context.view_paths.clone
46
46
  @_last_template ||= lookup_context.last_template
47
47
  end
48
- parts = @virtual_path.split('/')
49
- template = parts.pop
50
- prefix = parts.join('/')
51
-
52
- options = args[1] || {}
53
- options[:locals] ||= {}
54
- if view_stack.last
55
- options[:locals] = view_stack.last[:locals].merge!(options[:locals]) if view_stack.last[:locals]
56
- options[:object] ||= view_stack.last[:object] if view_stack.last[:object]
57
- end
58
- options[:template] = template
59
- # if prefix is active_scaffold_overrides we must try to render with this prefix in following paths
60
- if prefix != 'active_scaffold_overrides'
61
- options[:prefixes] = lookup_context.prefixes.drop((lookup_context.prefixes.find_index(prefix) || -1) + 1)
62
- else
63
- options[:prefixes] = ['active_scaffold_overrides']
64
- last_view_path = File.expand_path(File.dirname(File.dirname(lookup_context.last_template.inspect)), Rails.root)
65
- new_view_paths = view_paths.drop(view_paths.find_index { |path| path.to_s == last_view_path } + 1)
66
- if @lookup_context
67
- @lookup_context = build_lookup_context(new_view_paths)
68
- else
69
- lookup_context.view_paths = new_view_paths
70
- end
71
- end
72
- result = super options
48
+ result = super options_for_render_super(args[1])
73
49
  @lookup_context = @_lookup_context if @_lookup_context # rails 6
74
50
  lookup_context.view_paths = @_view_paths if @_view_paths # rails < 6
75
51
  lookup_context.last_template = @_last_template if @_last_template # rails < 6
@@ -103,6 +79,46 @@ module ActiveScaffold #:nodoc:
103
79
 
104
80
  private
105
81
 
82
+ def options_for_render_super(options)
83
+ options ||= {}
84
+ options[:locals] ||= {}
85
+ if view_stack.last
86
+ options[:locals] = view_stack.last[:locals].merge!(options[:locals]) if view_stack.last[:locals]
87
+ options[:object] ||= view_stack.last[:object] if view_stack.last[:object]
88
+ end
89
+
90
+ parts = @virtual_path.split('/')
91
+ options[:template] = parts.pop
92
+ prefix = parts.join('/')
93
+ # if prefix is active_scaffold_overrides we must try to render with this prefix in following paths
94
+ if prefix != 'active_scaffold_overrides'
95
+ options[:prefixes] = lookup_context.prefixes.drop((lookup_context.prefixes.find_index(prefix) || -1) + 1)
96
+ else
97
+ options[:prefixes] = ['active_scaffold_overrides']
98
+ update_view_paths
99
+ end
100
+ options
101
+ end
102
+
103
+ def update_view_paths
104
+ last_view_path =
105
+ if @lookup_context # rails 6
106
+ File.expand_path(File.dirname(File.dirname(@lookup_context.last_template.short_identifier.to_s)), Rails.root)
107
+ else
108
+ File.expand_path(File.dirname(File.dirname(lookup_context.last_template.inspect)), Rails.root)
109
+ end
110
+ new_view_paths = view_paths.drop(view_paths.find_index { |path| path.to_s == last_view_path } + 1)
111
+ if @lookup_context # rails 6
112
+ if respond_to? :build_lookup_context # rails 6.0
113
+ build_lookup_context(new_view_paths)
114
+ else # rails 6.1
115
+ @lookup_context = ActionView::LookupContext.new(new_view_paths)
116
+ end
117
+ else
118
+ lookup_context.view_paths = new_view_paths
119
+ end
120
+ end
121
+
106
122
  def render_embedded(options)
107
123
  require 'digest/md5'
108
124
 
@@ -153,5 +169,30 @@ module ActionView
153
169
  Base.class_eval do
154
170
  include ActiveScaffold::RenderingHelper
155
171
  end
172
+
173
+ if Gem.loaded_specs['rails'].version.segments.first >= 6
174
+ RenderingHelper.class_eval do
175
+ # override the render method to use our @lookup_context instead of the
176
+ # memoized @_lookup_context
177
+ def render(options = {}, locals = {}, &block)
178
+ case options
179
+ when Hash
180
+ in_rendering_context(options) do |_|
181
+ # previously set view paths and lookup context are lost here
182
+ # if you use view_renderer, so instead create a new renderer
183
+ # with our context
184
+ temp_renderer = ActionView::Renderer.new(@lookup_context)
185
+ if block_given?
186
+ temp_renderer.render_partial(self, options.merge(partial: options[:layout]), &block)
187
+ else
188
+ temp_renderer.render(self, options)
189
+ end
190
+ end
191
+ else
192
+ view_renderer.render_partial(self, partial: options, locals: locals, &block)
193
+ end
194
+ end
195
+ end
196
+ end
156
197
  end
157
198
  end
@@ -3,7 +3,7 @@ class Object
3
3
  if key.present?
4
4
  scope = [:active_scaffold, *options.delete(:scope)]
5
5
  options = options.reverse_merge(:scope => scope, :default => key.is_a?(String) ? key : key.to_s.titleize)
6
- text = I18n.translate(key.to_s, options).html_safe # rubocop:disable Rails/OutputSafety
6
+ text = I18n.translate(key.to_s, **options).html_safe # rubocop:disable Rails/OutputSafety
7
7
  # text = nil if text.include?('translation missing:')
8
8
  end
9
9
  text || key
@@ -409,9 +409,9 @@ module ActiveScaffold
409
409
  params_hash active_scaffold_embedded_params[:conditions]
410
410
  end
411
411
 
412
- def all_conditions
412
+ def all_conditions(include_id_condition = true)
413
413
  [
414
- id_condition, # for list with id (e.g. /users/:id/index)
414
+ (id_condition if include_id_condition), # for list with id (e.g. /users/:id/index)
415
415
  active_scaffold_conditions, # from the search modules
416
416
  conditions_for_collection, # from the dev
417
417
  conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred)
@@ -444,9 +444,11 @@ module ActiveScaffold
444
444
  def finder_options(options = {})
445
445
  search_conditions = all_conditions
446
446
 
447
+ sorting = options[:sorting]&.clause((grouped_columns_calculations if grouped_search?))
448
+ sorting = sorting.map(&Arel.method(:sql)) if sorting && active_scaffold_config.active_record?
447
449
  # create a general-use options array that's compatible with Rails finders
448
450
  finder_options = {
449
- :reorder => options[:sorting]&.clause((grouped_columns_calculations if grouped_search?)).map(&Arel.method(:sql)),
451
+ :reorder => sorting,
450
452
  :conditions => search_conditions
451
453
  }
452
454
  if active_scaffold_config.mongoid?
@@ -519,8 +521,8 @@ module ActiveScaffold
519
521
  @last_modified = query.maximum(:updated_at)
520
522
  end
521
523
 
522
- def calculate_query
523
- conditions = all_conditions
524
+ def calculate_query(id_condition = true)
525
+ conditions = all_conditions(id_condition)
524
526
  includes = active_scaffold_config.list.count_includes
525
527
  includes ||= active_scaffold_references if conditions.present?
526
528
  left_joins = active_scaffold_outer_joins
@@ -180,6 +180,17 @@ module ActiveScaffold
180
180
  end
181
181
  end
182
182
  end
183
+
184
+ def save_record_to_association(record, association, value, reverse = nil)
185
+ return unless association
186
+ if association.collection?
187
+ record.association(association.name).target << value
188
+ elsif reverse&.belongs_to?
189
+ value.send("#{reverse.name}=", record)
190
+ else
191
+ record.send("#{association.name}=", value)
192
+ end
193
+ end
183
194
  end
184
195
  end
185
196
  end
@@ -71,9 +71,9 @@ module ActiveScaffold
71
71
  end
72
72
  end
73
73
 
74
- def active_scaffold_subform_attributes(column, column_css_class = nil)
74
+ def active_scaffold_subform_attributes(column, column_css_class = nil, klass = nil)
75
75
  {
76
- :class => "sub-form #{active_scaffold_config_for(column.association.klass).subform.layout}-sub-form #{column_css_class} #{column.name}-sub-form",
76
+ :class => "sub-form #{active_scaffold_config_for(klass || column.association.klass).subform.layout}-sub-form #{column_css_class} #{column.name}-sub-form",
77
77
  :id => sub_form_id(:association => column.name)
78
78
  }
79
79
  end
@@ -308,17 +308,39 @@ module ActiveScaffold
308
308
  html
309
309
  end
310
310
 
311
- def active_scaffold_new_record_subform(column, record, html_options)
312
- subform_attrs = active_scaffold_subform_attributes(column).merge(style: 'display: none')
311
+ def active_scaffold_new_record_subform(column, record, html_options, new_record_attributes: nil, locals: {}, skip_link: false) # rubocop:disable Metrics/ParameterLists
312
+ klass =
313
+ if column.association.polymorphic? && column.association.belongs_to?
314
+ type = record.send(column.association.foreign_type)
315
+ column.association.klass(record) if type.present? && (column.options[:add_new] == true || type.in?(column.options[:add_new]))
316
+ else
317
+ column.association.klass
318
+ end
319
+ return content_tag(:div, '') unless klass
320
+ subform_attrs = active_scaffold_subform_attributes(column, nil, klass)
321
+ if record.send(column.name)&.new_record?
322
+ new_record = record.send(column.name)
323
+ else
324
+ subform_attrs[:style] = 'display: none'
325
+ end
326
+ subform_attrs[:class] << ' optional'
313
327
  scope = html_options[:name].scan(/record(.*)\[#{column.name}\]/).dig(0, 0)
314
- new_record = build_associated(column.association, record)
315
- subform = render(partial: subform_partial_for_column(column), locals: {column: column, parent_record: record, associated: [], show_blank_record: new_record, scope: scope})
328
+ new_record ||= klass.new(new_record_attributes)
329
+ locals = locals.reverse_merge(column: column, parent_record: record, associated: [], show_blank_record: new_record, scope: scope)
330
+ subform = render(partial: subform_partial_for_column(column, klass), locals: locals)
331
+ if column.options[:hide_subgroups]
332
+ toggable_id = "#{sub_form_id(association: column.name, id: record.id || generated_id(record) || 99_999_999_999)}-div"
333
+ subform << link_to_visibility_toggle(toggable_id, default_visible: false)
334
+ end
316
335
  html = content_tag(:div, subform, subform_attrs)
336
+ return html if skip_link
317
337
  html << active_scaffold_show_new_subform_link(column, record, html_options[:id], subform_attrs[:id])
318
338
  end
319
339
 
320
340
  def active_scaffold_show_new_subform_link(column, record, select_id, subform_id)
321
- link_to(as_(:create_new), '#', data: {select_id: select_id, subform_id: subform_id, subform_text: as_(:add_existing)}, class: 'show-new-subform')
341
+ data = {select_id: select_id, subform_id: subform_id, subform_text: as_(:add_existing), select_text: as_(:create_new)}
342
+ label = data[record.send(column.name)&.new_record? ? :subform_text : :select_text]
343
+ link_to(label, '#', data: data, class: 'show-new-subform')
322
344
  end
323
345
 
324
346
  def active_scaffold_file_with_remove_link(column, options, content, remove_file_prefix, controls_class, &block) # rubocop:disable Metrics/ParameterLists
@@ -469,20 +491,35 @@ module ActiveScaffold
469
491
  active_scaffold_enum_options(column, record)
470
492
  end
471
493
 
472
- selected = record.send(column.association.name)&.id if column.association
494
+ selected = record.send(column.association.name) if column.association
495
+ selected_id = selected&.id
473
496
  if options.present?
497
+ if column.options[:add_new]
498
+ html_options[:data] ||= {}
499
+ html_options[:data][:subform_id] = active_scaffold_subform_attributes(column)[:id]
500
+ radio_html_options = html_options.merge(class: html_options[:class] + ' hide-new-subform')
501
+ else
502
+ radio_html_options = html_options
503
+ end
474
504
  radios = options.map do |option|
475
- active_scaffold_radio_option(option, selected, column, html_options)
505
+ active_scaffold_radio_option(option, selected_id, column, radio_html_options)
476
506
  end
477
507
  if column.options[:include_blank]
478
508
  label = column.options[:include_blank]
479
509
  label = as_(column.options[:include_blank]) if column.options[:include_blank].is_a?(Symbol)
480
510
  radios.prepend content_tag(:label, radio_button(:record, column.name, '', html_options.merge(id: nil)) + label)
481
511
  end
512
+ if column.options[:add_new]
513
+ create_new_button = radio_button_tag(html_options[:name], '', selected&.new_record?, html_options.merge(id: nil, class: html_options[:class] + ' show-new-subform'))
514
+ radios << content_tag(:label, create_new_button << as_(:create_new)) <<
515
+ active_scaffold_new_record_subform(column, record, html_options, skip_link: true)
516
+ end
482
517
  safe_join radios
483
518
  else
484
- content_tag(:span, as_(:no_options), :class => "#{html_options[:class]} no-options", :id => html_options[:id]) <<
485
- hidden_field_tag(html_options[:name], '', :id => nil)
519
+ html = content_tag(:span, as_(:no_options), :class => "#{html_options[:class]} no-options", :id => html_options[:id])
520
+ html << hidden_field_tag(html_options[:name], '', :id => nil)
521
+ html << active_scaffold_new_record_subform(column, record, html_options) if column.options[:add_new]
522
+ html
486
523
  end
487
524
  end
488
525
 
@@ -628,8 +665,8 @@ module ActiveScaffold
628
665
  end
629
666
  alias override_input? override_input
630
667
 
631
- def subform_partial_for_column(column)
632
- subform_partial = "#{active_scaffold_config_for(column.association.klass).subform.layout}_subform"
668
+ def subform_partial_for_column(column, klass = nil)
669
+ subform_partial = "#{column.options[:layout] || active_scaffold_config_for(klass || column.association.klass).subform.layout}_subform"
633
670
  override_subform_partial(column, subform_partial) || subform_partial
634
671
  end
635
672
 
@@ -703,14 +740,14 @@ module ActiveScaffold
703
740
 
704
741
  # Minimum
705
742
  unless options[:min]
706
- min = validators.map { |v| v.options[:greater_than_or_equal] }.compact.max
743
+ min = validators.map { |v| v.options[:greater_than_or_equal_to] }.compact.max
707
744
  greater_than = validators.map { |v| v.options[:greater_than] }.compact.max
708
745
  numerical_constraints[:min] = [min, (greater_than + margin if greater_than)].compact.max
709
746
  end
710
747
 
711
748
  # Maximum
712
749
  unless options[:max]
713
- max = validators.map { |v| v.options[:less_than_or_equal] }.compact.min
750
+ max = validators.map { |v| v.options[:less_than_or_equal_to] }.compact.min
714
751
  less_than = validators.map { |v| v.options[:less_than] }.compact.min
715
752
  numerical_constraints[:max] = [max, (less_than - margin if less_than)].compact.min
716
753
  end
@@ -170,8 +170,12 @@ module ActiveScaffold
170
170
 
171
171
  def column_association_size(record, column, value)
172
172
  cached_counts = @counts&.dig(column.name)
173
- key = column.association.primary_key if count_on_association_class?(column)
174
- cached_counts ? cached_counts[record.send(key || :id)] || 0 : value.size
173
+ if cached_counts
174
+ key = column.association.primary_key if count_on_association_class?(column)
175
+ cached_counts[record.send(key || :id)] || 0
176
+ else
177
+ value.size
178
+ end
175
179
  end
176
180
 
177
181
  def format_number_value(value, options = {})
@@ -427,16 +431,16 @@ module ActiveScaffold
427
431
 
428
432
  # CALCULATIONS
429
433
 
430
- def column_calculation(column)
434
+ def column_calculation(column, id_condition: true)
431
435
  if column.calculate.instance_of? Proc
432
436
  column.calculate.call(@records)
433
437
  else
434
- calculate_query.calculate(column.calculate, column.name)
438
+ calculate_query(id_condition).calculate(column.calculate, column.name)
435
439
  end
436
440
  end
437
441
 
438
- def render_column_calculation(column)
439
- calculation = column_calculation(column)
442
+ def render_column_calculation(column, id_condition: true)
443
+ calculation = column_calculation(column, id_condition: id_condition)
440
444
  override_formatter = "render_#{column.name}_#{column.calculate.is_a?(Proc) ? :calculate : column.calculate}"
441
445
  calculation = send(override_formatter, calculation) if respond_to? override_formatter
442
446
  format_column_calculation(column, calculation)