active_scaffold 3.6.0.pre → 3.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +39 -0
  3. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  4. data/app/assets/javascripts/jquery/active_scaffold.js +35 -4
  5. data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
  6. data/app/assets/stylesheets/active_scaffold_layout.css +52 -29
  7. data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
  8. data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
  9. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
  10. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
  11. data/config/locales/de.yml +2 -1
  12. data/config/locales/en.yml +1 -0
  13. data/config/locales/es.yml +1 -0
  14. data/config/locales/fr.yml +2 -1
  15. data/config/locales/hu.yml +1 -0
  16. data/config/locales/ja.yml +1 -0
  17. data/config/locales/ru.yml +1 -0
  18. data/lib/active_scaffold.rb +8 -3
  19. data/lib/active_scaffold/actions/common_search.rb +11 -8
  20. data/lib/active_scaffold/actions/core.rb +79 -51
  21. data/lib/active_scaffold/actions/create.rb +27 -27
  22. data/lib/active_scaffold/actions/delete.rb +1 -1
  23. data/lib/active_scaffold/actions/field_search.rb +52 -42
  24. data/lib/active_scaffold/actions/list.rb +106 -23
  25. data/lib/active_scaffold/actions/nested.rb +59 -42
  26. data/lib/active_scaffold/actions/show.rb +3 -3
  27. data/lib/active_scaffold/actions/subform.rb +9 -16
  28. data/lib/active_scaffold/actions/update.rb +95 -77
  29. data/lib/active_scaffold/attribute_params.rb +93 -68
  30. data/lib/active_scaffold/bridges/active_storage.rb +6 -0
  31. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +33 -0
  32. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
  33. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
  34. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
  35. data/lib/active_scaffold/bridges/bitfields.rb +1 -0
  36. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  37. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +6 -0
  38. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  39. data/lib/active_scaffold/bridges/date_picker/helper.rb +46 -41
  40. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  41. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +2 -2
  42. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  43. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +3 -1
  44. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  45. data/lib/active_scaffold/bridges/record_select/helpers.rb +3 -7
  46. data/lib/active_scaffold/bridges/shared/date_bridge.rb +19 -18
  47. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  48. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +20 -3
  49. data/lib/active_scaffold/config/base.rb +58 -34
  50. data/lib/active_scaffold/config/core.rb +31 -12
  51. data/lib/active_scaffold/config/delete.rb +12 -1
  52. data/lib/active_scaffold/config/list.rb +17 -7
  53. data/lib/active_scaffold/config/mark.rb +1 -1
  54. data/lib/active_scaffold/configurable.rb +5 -3
  55. data/lib/active_scaffold/constraints.rb +21 -19
  56. data/lib/active_scaffold/core.rb +35 -26
  57. data/lib/active_scaffold/data_structures/action_columns.rb +1 -1
  58. data/lib/active_scaffold/data_structures/action_link.rb +34 -16
  59. data/lib/active_scaffold/data_structures/action_links.rb +9 -11
  60. data/lib/active_scaffold/data_structures/association/abstract.rb +35 -13
  61. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  62. data/lib/active_scaffold/data_structures/association/active_record.rb +5 -1
  63. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  64. data/lib/active_scaffold/data_structures/column.rb +49 -58
  65. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  66. data/lib/active_scaffold/data_structures/nested_info.rb +20 -18
  67. data/lib/active_scaffold/data_structures/sorting.rb +5 -0
  68. data/lib/active_scaffold/delayed_setup.rb +16 -6
  69. data/lib/active_scaffold/extensions/action_controller_rendering.rb +1 -1
  70. data/lib/active_scaffold/extensions/action_view_rendering.rb +34 -14
  71. data/lib/active_scaffold/extensions/cow_proxy.rb +50 -2
  72. data/lib/active_scaffold/extensions/localize.rb +3 -1
  73. data/lib/active_scaffold/extensions/routing_mapper.rb +2 -2
  74. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  75. data/lib/active_scaffold/finder.rb +81 -46
  76. data/lib/active_scaffold/helpers/action_link_helpers.rb +47 -21
  77. data/lib/active_scaffold/helpers/association_helpers.rb +13 -11
  78. data/lib/active_scaffold/helpers/controller_helpers.rb +14 -11
  79. data/lib/active_scaffold/helpers/form_column_helpers.rb +133 -99
  80. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  81. data/lib/active_scaffold/helpers/id_helpers.rb +4 -0
  82. data/lib/active_scaffold/helpers/list_column_helpers.rb +76 -49
  83. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  84. data/lib/active_scaffold/helpers/search_column_helpers.rb +25 -30
  85. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  86. data/lib/active_scaffold/helpers/view_helpers.rb +31 -22
  87. data/lib/active_scaffold/orm_checks.rb +2 -2
  88. data/lib/active_scaffold/paginator.rb +1 -3
  89. data/lib/active_scaffold/registry.rb +11 -0
  90. data/lib/active_scaffold/responds_to_parent.rb +6 -5
  91. data/lib/active_scaffold/tableless.rb +6 -8
  92. data/lib/active_scaffold/version.rb +1 -1
  93. data/shoulda_macros/macros.rb +3 -1
  94. data/test/bridges/paperclip_test.rb +1 -1
  95. data/test/company.rb +2 -2
  96. data/test/data_structures/action_columns_test.rb +2 -2
  97. data/test/data_structures/column_test.rb +3 -6
  98. data/test/data_structures/columns_test.rb +2 -2
  99. data/test/extensions/active_record_test.rb +4 -4
  100. data/test/extensions/routing_mapper_test.rb +2 -2
  101. data/test/helpers/list_column_helpers_test.rb +3 -1
  102. data/test/misc/active_record_permissions_test.rb +2 -2
  103. data/test/misc/attribute_params_test.rb +4 -0
  104. data/test/misc/configurable_test.rb +10 -10
  105. data/test/misc/convert_numbers_format_test.rb +4 -0
  106. data/test/mock_app/app/assets/config/manifest.js +0 -0
  107. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  108. data/test/mock_app/app/controllers/people_controller.rb +3 -1
  109. data/test/mock_app/config/application.rb +1 -0
  110. data/test/mock_app/config/routes.rb +4 -1
  111. data/test/mock_app/db/schema.rb +2 -0
  112. data/test/performance/list_cars_performance_test.rb +34 -0
  113. data/test/performance/list_people_performance_test.rb +31 -0
  114. data/test/performance_test_help.rb +3 -0
  115. data/test/test_helper.rb +2 -1
  116. metadata +22 -12
  117. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  118. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -5
@@ -57,7 +57,7 @@ module ActiveScaffold
57
57
 
58
58
  def active_scaffold_human_condition_boolean(column, value)
59
59
  attribute = column.active_record_class.human_attribute_name(column.name)
60
- label = as_(ActiveScaffold::Core.column_type_cast(value, column.column) ? :true : :false)
60
+ label = as_(ActiveScaffold::Core.column_type_cast(value, column.column) ? :true : :false) # rubocop:disable Lint/BooleanSymbol
61
61
  as_(:boolean, :scope => :human_conditions, :column => attribute, :value => label)
62
62
  end
63
63
  alias active_scaffold_human_condition_checkbox active_scaffold_human_condition_boolean
@@ -10,6 +10,10 @@ module ActiveScaffold
10
10
  'as_' + id_from_controller(controller)
11
11
  end
12
12
 
13
+ def nested?
14
+ false # will be overrided in AS controllers with helper_method
15
+ end
16
+
13
17
  def nested_parent_id
14
18
  nested_parent_record.id
15
19
  end
@@ -10,7 +10,7 @@ module ActiveScaffold
10
10
  else
11
11
  value = nil
12
12
  end
13
- value = ' '.html_safe if value.nil? || value.blank? # fix for IE 6
13
+ value = ' '.html_safe if value.nil? || value.blank? # fix for IE 6 # rubocop:disable Rails/OutputSafety
14
14
  value
15
15
  rescue StandardError => e
16
16
  logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column = :#{column.name} in #{controller.class}, record: #{record.inspect}"
@@ -19,7 +19,7 @@ module ActiveScaffold
19
19
 
20
20
  def get_column_method(record, column)
21
21
  # check for an override helper
22
- column.list_method ||= begin
22
+ ActiveScaffold::Registry.cache :column_methods, column.cache_key do
23
23
  if (method = column_override(column))
24
24
  # we only pass the record as the argument. we previously also passed the formatted_value,
25
25
  # but mike perham pointed out that prohibited the usage of overrides to improve on the
@@ -47,8 +47,8 @@ module ActiveScaffold
47
47
  render_action_link(link, record, :link => text, :authorized => authorized, :not_authorized_reason => reason)
48
48
  elsif inplace_edit?(record, column)
49
49
  active_scaffold_inplace_edit(record, column, :formatted_column => text)
50
- elsif active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.wrap_tag
51
- content_tag active_scaffold_config.list.wrap_tag, text
50
+ elsif column_wrap_tag
51
+ content_tag column_wrap_tag, text
52
52
  else
53
53
  text
54
54
  end
@@ -57,6 +57,11 @@ module ActiveScaffold
57
57
  raise e
58
58
  end
59
59
 
60
+ def column_wrap_tag
61
+ return @_column_wrap_tag if defined? @_column_wrap_tag
62
+ @_column_wrap_tag = (active_scaffold_config.list.wrap_tag if active_scaffold_config.actions.include?(:list))
63
+ end
64
+
60
65
  # There are two basic ways to clean a column's value: h() and sanitize(). The latter is useful
61
66
  # when the column contains *valid* html data, and you want to just disable any scripting. People
62
67
  # can always use field overrides to clean data one way or the other, but having this override
@@ -127,20 +132,21 @@ module ActiveScaffold
127
132
 
128
133
  # the naming convention for overriding column types with helpers
129
134
  def override_column_ui(list_ui)
130
- @_column_ui_overrides ||= {}
131
- return @_column_ui_overrides[list_ui] if @_column_ui_overrides.include? list_ui
132
- method = "active_scaffold_column_#{list_ui}"
133
- @_column_ui_overrides[list_ui] = (method if respond_to? method)
135
+ ActiveScaffold::Registry.cache :column_ui_overrides, list_ui do
136
+ method = "active_scaffold_column_#{list_ui}"
137
+ method if respond_to? method
138
+ end
134
139
  end
135
140
  alias override_column_ui? override_column_ui
136
141
 
137
142
  ##
138
143
  ## Formatting
139
144
  ##
145
+ FORM_UI_WITH_OPTIONS = %i[select radio].freeze
140
146
  def format_column_value(record, column, value = nil)
141
147
  value ||= record.send(column.name) unless record.nil?
142
148
  if column.association.nil?
143
- if %i[select radio].include?(column.form_ui) && column.options[:options]
149
+ if FORM_UI_WITH_OPTIONS.include?(column.form_ui) && column.options[:options]
144
150
  text, val = column.options[:options].find { |t, v| (v.nil? ? t : v).to_s == value.to_s }
145
151
  value = active_scaffold_translated_option(column, text, val).first if text
146
152
  end
@@ -153,7 +159,7 @@ module ActiveScaffold
153
159
  end
154
160
  else
155
161
  if column.association.collection?
156
- associated_size = value.size if column.associated_number? # get count before cache association
162
+ associated_size = column_association_size(record, column, value) if column.associated_number? # get count before cache association
157
163
  if column.association.respond_to_target? && !value.loaded?
158
164
  cache_association(record.association(column.name), column, associated_size)
159
165
  end
@@ -162,20 +168,27 @@ module ActiveScaffold
162
168
  end
163
169
  end
164
170
 
171
+ def column_association_size(record, column, value)
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
175
+ end
176
+
165
177
  def format_number_value(value, options = {})
166
178
  if value
167
- value = case options[:format]
168
- when :size
169
- number_to_human_size(value, options[:i18n_options] || {})
170
- when :percentage
171
- number_to_percentage(value, options[:i18n_options] || {})
172
- when :currency
173
- number_to_currency(value, options[:i18n_options] || {})
174
- when :i18n_number
175
- send("number_with_#{value.is_a?(Integer) ? 'delimiter' : 'precision'}", value, options[:i18n_options] || {})
176
- else
177
- value
178
- end
179
+ value =
180
+ case options[:format]
181
+ when :size
182
+ number_to_human_size(value, options[:i18n_options] || {})
183
+ when :percentage
184
+ number_to_percentage(value, options[:i18n_options] || {})
185
+ when :currency
186
+ number_to_currency(value, options[:i18n_options] || {})
187
+ when :i18n_number
188
+ send("number_with_#{value.is_a?(Integer) ? 'delimiter' : 'precision'}", value, options[:i18n_options] || {})
189
+ else
190
+ value
191
+ end
179
192
  end
180
193
  clean_column_value(value)
181
194
  end
@@ -196,18 +209,26 @@ module ActiveScaffold
196
209
  end
197
210
  end
198
211
 
212
+ def association_join_text(column = nil)
213
+ column_value = column&.association_join_text
214
+ return column_value if column_value
215
+ return @_association_join_text if defined? @_association_join_text
216
+ @_association_join_text = active_scaffold_config.list.association_join_text
217
+ end
218
+
199
219
  def format_collection_association_value(value, column, label_method, size)
200
- if column.associated_limit.nil?
220
+ associated_limit = column.associated_limit
221
+ if associated_limit.nil?
201
222
  firsts = value.collect(&label_method)
202
- safe_join firsts, active_scaffold_config.list.association_join_text
203
- elsif column.associated_limit.zero?
223
+ safe_join firsts, association_join_text(column)
224
+ elsif associated_limit.zero?
204
225
  size if column.associated_number?
205
226
  else
206
- firsts = value.loaded? ? value[0, column.associated_limit] : value.limit(column.associated_limit)
227
+ firsts = value.loaded? ? value[0, associated_limit] : value.limit(associated_limit)
207
228
  firsts = firsts.map(&label_method)
208
- firsts << '…' if value.size > column.associated_limit
209
- text = safe_join firsts, active_scaffold_config.list.association_join_text
210
- text << " (#{size})" if column.associated_number? && column.associated_limit && value.size > column.associated_limit
229
+ firsts << '…' if value.size > associated_limit
230
+ text = safe_join firsts, association_join_text(column)
231
+ text << " (#{size})" if column.associated_number? && associated_limit && value.size > associated_limit
211
232
  text
212
233
  end
213
234
  end
@@ -237,7 +258,7 @@ module ActiveScaffold
237
258
  empty_field_text
238
259
  elsif column_value.is_a?(Time) || column_value.is_a?(Date)
239
260
  l(column_value, :format => options[:format] || :default)
240
- elsif [FalseClass, TrueClass].include?(column_value.class)
261
+ elsif !!column_value == column_value # rubocop:disable Style/DoubleNegation fast check for boolean
241
262
  as_(column_value.to_s.to_sym)
242
263
  else
243
264
  column_value.to_s
@@ -246,15 +267,21 @@ module ActiveScaffold
246
267
  end
247
268
 
248
269
  def cache_association(association, column, size)
270
+ associated_limit = column.associated_limit
249
271
  # we are not using eager loading, cache firsts records in order not to query the database for whole association in a future
250
- if column.associated_limit.nil?
272
+ if associated_limit.nil?
251
273
  logger.warn "ActiveScaffold: Enable eager loading for #{column.name} association to reduce SQL queries"
252
- elsif column.associated_limit.positive?
274
+ elsif associated_limit.positive?
253
275
  # load at least one record more, is needed to display '...'
254
- association.target = association.reader.limit(column.associated_limit + 1).select(column.select_associated_columns || "#{association.klass.quoted_table_name}.*").to_a
276
+ association.target = association.reader.limit(associated_limit + 1).select(column.select_associated_columns || "#{association.klass.quoted_table_name}.*").to_a
255
277
  elsif @cache_associations
256
278
  # set array with at least one element if size > 0, so blank? or present? works, saving [nil] may cause exceptions
257
- association.target = size.to_i.zero? ? [] : [association.klass.new]
279
+ association.target =
280
+ if size.to_i.zero?
281
+ []
282
+ else
283
+ ActiveScaffold::Registry.cache(:cached_empty_association, association.klass) { [association.klass.new] }
284
+ end
258
285
  end
259
286
  end
260
287
 
@@ -265,14 +292,9 @@ module ActiveScaffold
265
292
  def inplace_edit?(record, column)
266
293
  return unless column.inplace_edit
267
294
  if controller.respond_to?(:update_authorized?, true)
268
- if controller.method(:update_authorized?).parameters.size == 2
269
- return Array(controller.send(:update_authorized?, record, column.name))[0]
270
- else
271
- ActiveSupport::Deprecation.warn 'add column = nil parameter to update_authorized? on your controller'
272
- editable = Array(controller.send(:update_authorized?, record))[0]
273
- end
295
+ return Array(controller.send(:update_authorized?, record, column.name))[0]
274
296
  end
275
- editable || record.authorized_for?(:crud_type => :update, :column => column.name)
297
+ record.authorized_for?(:crud_type => :update, :column => column.name)
276
298
  end
277
299
 
278
300
  def inplace_edit_cloning?(column)
@@ -280,17 +302,21 @@ module ActiveScaffold
280
302
  end
281
303
 
282
304
  def active_scaffold_inplace_edit_tag_options(record, column)
283
- id_options = {:id => record.id.to_s, :action => 'update_column', :name => column.name.to_s}
284
- tag_options = {:id => element_cell_id(id_options), :class => 'in_place_editor_field',
285
- :title => as_(:click_to_edit), :data => {:ie_id => record.to_param}}
305
+ @_inplace_edit_title ||= as_(:click_to_edit)
306
+ cell_id = ActiveScaffold::Registry.cache :inplace_edit_id, column.cache_key do
307
+ element_cell_id(id: '--ID--', action: 'update_column', name: column.name.to_s)
308
+ end
309
+ tag_options = {id: cell_id.sub('--ID--', record.id.to_s), class: 'in_place_editor_field',
310
+ title: @_inplace_edit_title, data: {:ie_id => record.to_param}}
286
311
  tag_options[:data][:ie_update] = column.inplace_edit if column.inplace_edit != true
287
312
  tag_options
288
313
  end
289
314
 
290
315
  def active_scaffold_inplace_edit(record, column, options = {})
291
316
  formatted_column = options[:formatted_column] || format_column_value(record, column)
292
- content_tag(:span, as_(:inplace_edit_handle), :class => 'handle') <<
293
- content_tag(:span, formatted_column, active_scaffold_inplace_edit_tag_options(record, column))
317
+ @_inplace_edit_handle ||= content_tag(:span, as_(:inplace_edit_handle), :class => 'handle')
318
+ span = content_tag(:span, formatted_column, active_scaffold_inplace_edit_tag_options(record, column))
319
+ @_inplace_edit_handle + span
294
320
  end
295
321
 
296
322
  def inplace_edit_control(column)
@@ -311,6 +337,7 @@ module ActiveScaffold
311
337
  'as_inplace_pattern'
312
338
  end
313
339
 
340
+ INPLACE_EDIT_PLURAL_FORM_UI = %i[select record_select].freeze
314
341
  def inplace_edit_data(column)
315
342
  data = {}
316
343
  data[:ie_url] = url_for(params_for(:action => 'update_column', :column => column.name, :id => '__id__'))
@@ -329,7 +356,7 @@ module ActiveScaffold
329
356
  data[:ie_mode] = :clone
330
357
  elsif column.inplace_edit == :ajax
331
358
  url = url_for(params_for(:controller => params_for[:controller], :action => 'render_field', :id => '__id__', :update_column => column.name))
332
- plural = column.association&.collection? && !override_form_field?(column) && %i[select record_select].include?(column.form_ui)
359
+ plural = column.association&.collection? && !override_form_field?(column) && INPLACE_EDIT_PLURAL_FORM_UI.include?(column.form_ui)
333
360
  data[:ie_render_url] = url
334
361
  data[:ie_mode] = :ajax
335
362
  data[:ie_plural] = plural
@@ -368,8 +395,8 @@ module ActiveScaffold
368
395
  :ie_mode => :inline_checkbox,
369
396
  :ie_url => url_for(params_for(:action => 'mark', :id => '__id__'))
370
397
  }
371
- else
372
- tag_options[:data] = inplace_edit_data(column) if column.inplace_edit
398
+ elsif column.inplace_edit
399
+ tag_options[:data] = inplace_edit_data(column)
373
400
  end
374
401
  content_tag(:th, column_heading_value(column, sorting, sort_direction) + inplace_edit_control(column), tag_options)
375
402
  end
@@ -21,8 +21,8 @@ module ActiveScaffold
21
21
  start_number = 1 if start_number <= 0
22
22
  if current_page.pager.infinite?
23
23
  offsets = [20, 100]
24
- else
25
- end_number = current_page.pager.last.number if end_number > current_page.pager.last.number
24
+ elsif end_number > current_page.pager.last.number
25
+ end_number = current_page.pager.last.number
26
26
  end
27
27
 
28
28
  html = []
@@ -29,25 +29,22 @@ module ActiveScaffold
29
29
  send(method, record, options)
30
30
 
31
31
  # fallback: we get to make the decision
32
- else
33
- if column.association || column.virtual?
34
- active_scaffold_search_text(column, options)
35
-
36
- else # regular model attribute column
37
- # if we (or someone else) have created a custom render option for the column type, use that
38
- if (method = override_search(column.column.type))
39
- send(method, column, options)
40
- # if we (or someone else) have created a custom render option for the column type, use that
41
- elsif (method = override_input(column.column.type))
42
- send(method, column, options)
43
- # final ultimate fallback: use rails' generic input method
44
- else
45
- # for textual fields we pass different options
46
- text_types = %i[text string integer float decimal]
47
- options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
48
- text_field(:record, column.name, options.merge(column.options))
49
- end
50
- end
32
+ elsif column.association || column.virtual?
33
+ active_scaffold_search_text(column, options)
34
+
35
+ elsif (method = override_search(column.column.type))
36
+ # if we (or someone else) have created a custom render option for the column type, use that
37
+ send(method, column, options)
38
+
39
+ elsif (method = override_input(column.column.type))
40
+ # if we (or someone else) have created a custom render option for the column type, use that
41
+ send(method, column, options)
42
+
43
+ else # final ultimate fallback: use rails' generic input method
44
+ # for textual fields we pass different options
45
+ text_types = %i[text string integer float decimal]
46
+ options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
47
+ text_field(:record, column.name, options.merge(column.options))
51
48
  end
52
49
  rescue StandardError => e
53
50
  logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column = :#{column.name} in #{controller.class}"
@@ -61,8 +58,10 @@ module ActiveScaffold
61
58
 
62
59
  def search_attribute(column, record)
63
60
  column_options = active_scaffold_search_options(column).merge(:object => record)
64
- field = active_scaffold_search_for column, column_options
65
- %(<dl><dt>#{label_tag search_label_for(column, column_options), search_column_label(column, record)}</dt><dd>#{field}</dd></dl>).html_safe
61
+ content_tag :dl do
62
+ content_tag(:dt, label_tag(search_label_for(column, column_options), search_column_label(column, record))) <<
63
+ content_tag(:dd, active_scaffold_search_for(column, column_options))
64
+ end
66
65
  end
67
66
 
68
67
  def search_label_for(column, options)
@@ -135,8 +134,8 @@ module ActiveScaffold
135
134
  def active_scaffold_search_boolean(column, options)
136
135
  select_options = []
137
136
  select_options << [as_(:_select_), nil]
138
- select_options << [as_(:true), true]
139
- select_options << [as_(:false), false]
137
+ select_options << [as_(:true), true] # rubocop:disable Lint/BooleanSymbol
138
+ select_options << [as_(:false), false] # rubocop:disable Lint/BooleanSymbol
140
139
 
141
140
  select_tag(options[:name], options_for_select(select_options, ActiveScaffold::Core.column_type_cast(options[:value], column.column)), :id => options[:id])
142
141
  end
@@ -166,7 +165,7 @@ module ActiveScaffold
166
165
  def active_scaffold_search_null(column, options)
167
166
  select_options = []
168
167
  select_options << [as_(:_select_), nil]
169
- select_options.concat ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] }
168
+ select_options.concat(ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] })
170
169
  select_tag(options[:name], options_for_select(select_options, options[:value]), :id => options[:id])
171
170
  end
172
171
 
@@ -187,7 +186,7 @@ module ActiveScaffold
187
186
  select_options.unshift(*comparators)
188
187
  end
189
188
  if include_null_comparators? column
190
- select_options.concat ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] }
189
+ select_options.concat(ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] })
191
190
  end
192
191
  select_options
193
192
  end
@@ -205,11 +204,7 @@ module ActiveScaffold
205
204
  opt_value, from_value, to_value = field_search_params_range_values(column)
206
205
 
207
206
  select_options = active_scaffold_search_range_comparator_options(column)
208
- if active_scaffold_search_range_string?(column)
209
- text_field_size = 15
210
- else
211
- text_field_size = 10
212
- end
207
+ text_field_size = active_scaffold_search_range_string?(column) ? 15 : 10
213
208
  opt_value ||= select_options[0][1]
214
209
 
215
210
  from_value = controller.class.condition_value_for_numeric(column, from_value)
@@ -14,12 +14,10 @@ module ActiveScaffold
14
14
  # second, check if the dev has specified a valid list_ui for this column
15
15
  elsif column.show_ui && (method = override_show_column_ui(column.show_ui))
16
16
  send(method, value_record, column)
17
+ elsif column.column && (method = override_show_column_ui(column.column.type))
18
+ send(method, value_record, column)
17
19
  else
18
- if column.column && (method = override_show_column_ui(column.column.type))
19
- send(method, value_record, column)
20
- else
21
- get_column_value(record, column)
22
- end
20
+ get_column_value(record, column)
23
21
  end
24
22
  end
25
23
 
@@ -17,8 +17,10 @@ module ActiveScaffold
17
17
  ## Delegates
18
18
  ##
19
19
 
20
- def active_scaffold_controller_for(*args)
21
- controller.class.active_scaffold_controller_for(*args)
20
+ def active_scaffold_controller_for(klass)
21
+ ActiveScaffold::Registry.cache :as_controller, klass do
22
+ controller.class.active_scaffold_controller_for(klass)
23
+ end
22
24
  end
23
25
 
24
26
  ##
@@ -56,17 +58,22 @@ module ActiveScaffold
56
58
 
57
59
  # a general-use loading indicator (the "stuff is happening, please wait" feedback)
58
60
  def loading_indicator_tag(options)
59
- image_tag 'active_scaffold/indicator.gif', :style => 'visibility:hidden;', :id => loading_indicator_id(options), :alt => 'loading indicator', :class => 'loading-indicator'
61
+ # it's call many times and we can cache same result
62
+ @_loading_indicator_path ||= image_path('active_scaffold/indicator.gif')
63
+ # it's call many times in long lists, image_tag is a bit slower
64
+ tag :img, src: @_loading_indicator_path, style: 'visibility:hidden;', id: loading_indicator_id(options), alt: 'loading indicator', class: 'loading-indicator'
60
65
  end
61
66
 
62
67
  # Creates a javascript-based link that toggles the visibility of some element on the page.
63
- # By default, it toggles the visibility of the sibling after the one it's nested in. You may pass custom javascript logic in options[:of] to change that, though. For example, you could say :of => '$("my_div_id")'.
68
+ # By default, it toggles the visibility of the sibling after the one it's nested in.
69
+ # You may pass custom javascript logic in options[:of] to change that, though. For example, you could say :of => '$("my_div_id")'.
64
70
  # You may also flag whether the other element is visible by default or not, and the initial text will adjust accordingly.
65
71
  def link_to_visibility_toggle(id, options = {})
66
- options[:default_visible] = true if options[:default_visible].nil?
67
72
  options[:hide_label] ||= as_(:hide)
68
73
  options[:show_label] ||= as_(:show_block)
69
- link_to options[:default_visible] ? options[:hide_label] : options[:show_label], '#', :data => {:show => options[:show_label], :hide => options[:hide_label], :toggable => id}, :style => 'display: none;', :class => 'as-js-button visibility-toggle'
74
+ label = options[:default_visible].nil? || options[:default_visible] ? options[:hide_label] : options[:show_label]
75
+ data = {:show => options[:show_label], :hide => options[:hide_label], :toggable => id}
76
+ link_to label, '#', :data => data, :style => 'display: none;', :class => 'as-js-button visibility-toggle'
70
77
  end
71
78
 
72
79
  def list_row_class_method(record)
@@ -80,6 +87,10 @@ module ActiveScaffold
80
87
  class_override_helper ? send(class_override_helper, record) : ''
81
88
  end
82
89
 
90
+ def list_row_attributes(tr_class, tr_id, data_refresh)
91
+ {class: "record #{tr_class}", id: tr_id, data: {refresh: data_refresh}}
92
+ end
93
+
83
94
  def column_attributes(column, record)
84
95
  method = override_helper column, 'column_attributes'
85
96
  return send(method, record) if method
@@ -87,15 +98,14 @@ module ActiveScaffold
87
98
  end
88
99
 
89
100
  def column_class(column, column_value, record)
90
- @_column_classes ||= {}
91
- @_column_classes[column.name] ||= begin
101
+ classes = ActiveScaffold::Registry.cache :column_classes, column.cache_key do
92
102
  classes = "#{column.name}-column "
93
103
  classes << 'sorted ' if active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.user.sorting.sorts_on?(column)
94
104
  classes << 'numeric ' if column.number?
95
- classes << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc)
105
+ classes << column.css_class << ' ' unless column.css_class.nil? || column.css_class.is_a?(Proc)
96
106
  classes
97
107
  end
98
- classes = "#{@_column_classes[column.name]} "
108
+ classes = classes.dup
99
109
  classes << 'empty ' if column_empty? column_value
100
110
  classes << 'in_place_editor_field ' if inplace_edit?(record, column) || column.list_ui == :marked
101
111
  if column.css_class.is_a?(Proc)
@@ -118,18 +128,23 @@ module ActiveScaffold
118
128
  classes
119
129
  end
120
130
 
131
+ def as_main_div_data
132
+ params[:eid] ? {eid: id_from_controller(params[:eid])} : {}
133
+ end
134
+
121
135
  def column_empty?(column_value)
136
+ @_empty_values ||= ['&nbsp;', empty_field_text].compact
122
137
  empty = column_value.nil?
123
138
  # column_value != false would force boolean to be cast to integer
124
139
  # when comparing to column_value of IPAddr class (PostgreSQL inet column type)
125
- # rubocop:disable Style/YodaCondition
126
- empty ||= false != column_value && column_value.blank?
127
- empty ||= ['&nbsp;', empty_field_text].include? column_value if column_value.is_a? String
140
+ empty ||= false != column_value && column_value.blank? # rubocop:disable Style/YodaCondition
141
+ empty ||= @_empty_values.include? column_value
128
142
  empty
129
143
  end
130
144
 
131
145
  def empty_field_text
132
- active_scaffold_config.list.empty_field_text if active_scaffold_config.actions.include?(:list)
146
+ return @_empty_field_text if defined? @_empty_field_text
147
+ @_empty_field_text = (active_scaffold_config.list.empty_field_text if active_scaffold_config.actions.include?(:list))
133
148
  end
134
149
 
135
150
  def as_slider(options)
@@ -150,11 +165,7 @@ module ActiveScaffold
150
165
  end
151
166
 
152
167
  def override_helper(column, suffix)
153
- hash = @_override_helpers ||= {}
154
- hash = hash[suffix] ||= {}
155
- hash = hash[column.active_record_class.name] ||= {}
156
- return hash[column.name] if hash.include? column.name
157
- hash[column.name] = begin
168
+ ActiveScaffold::Registry.cache suffix, column.cache_key do
158
169
  method_with_class = override_helper_name(column, suffix, true)
159
170
  if respond_to?(method_with_class)
160
171
  method_with_class
@@ -205,9 +216,7 @@ module ActiveScaffold
205
216
  object = instance_variable_get("@#{object}") unless object.respond_to?(:to_model)
206
217
  object = convert_to_model(object)
207
218
 
208
- if object.class.respond_to?(:model_name)
209
- options[:object_name] ||= object.class.model_name.human.downcase
210
- end
219
+ options[:object_name] ||= object.class.model_name.human.downcase if object.class.respond_to?(:model_name)
211
220
 
212
221
  object
213
222
  end