active_scaffold 3.6.20 → 3.7.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.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +47 -0
  3. data/README.md +29 -16
  4. data/app/assets/javascripts/jquery/active_scaffold.js +106 -68
  5. data/app/assets/javascripts/jquery/active_scaffold_chosen.js +6 -5
  6. data/app/assets/javascripts/jquery/tiny_mce_bridge.js +18 -4
  7. data/app/assets/stylesheets/active_scaffold_layout.css +13 -2
  8. data/app/views/active_scaffold_overrides/_base_form.html.erb +5 -1
  9. data/app/views/active_scaffold_overrides/_field_search.html.erb +1 -0
  10. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +2 -1
  11. data/app/views/active_scaffold_overrides/_render_field.js.erb +24 -13
  12. data/config/locales/de.yml +6 -3
  13. data/config/locales/en.yml +3 -0
  14. data/config/locales/es.yml +3 -0
  15. data/config/locales/fr.yml +9 -6
  16. data/config/locales/hu.yml +20 -17
  17. data/config/locales/ja.yml +83 -80
  18. data/config/locales/ru.yml +17 -14
  19. data/lib/active_scaffold/actions/common_search.rb +2 -2
  20. data/lib/active_scaffold/actions/core.rb +30 -10
  21. data/lib/active_scaffold/actions/field_search.rb +9 -6
  22. data/lib/active_scaffold/actions/nested.rb +7 -7
  23. data/lib/active_scaffold/actions/update.rb +3 -3
  24. data/lib/active_scaffold/attribute_params.rb +22 -70
  25. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +0 -3
  26. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +6 -6
  27. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +7 -7
  28. data/lib/active_scaffold/bridges/active_storage.rb +3 -0
  29. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +2 -2
  30. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +2 -2
  31. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +12 -14
  32. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +2 -2
  33. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
  34. data/lib/active_scaffold/bridges/chosen/helpers.rb +10 -10
  35. data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +7 -7
  36. data/lib/active_scaffold/bridges/date_picker/ext.rb +20 -9
  37. data/lib/active_scaffold/bridges/date_picker/helper.rb +9 -9
  38. data/lib/active_scaffold/bridges/date_picker.rb +2 -0
  39. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -3
  40. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +5 -5
  41. data/lib/active_scaffold/bridges/file_column/form_ui.rb +1 -1
  42. data/lib/active_scaffold/bridges/file_column/list_ui.rb +3 -3
  43. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +1 -1
  44. data/lib/active_scaffold/bridges/paper_trail/actions.rb +4 -1
  45. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -3
  46. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  47. data/lib/active_scaffold/bridges/record_select/helpers.rb +17 -17
  48. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +6 -6
  49. data/lib/active_scaffold/bridges/tiny_mce.rb +1 -1
  50. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +6 -11
  51. data/lib/active_scaffold/bridges.rb +0 -3
  52. data/lib/active_scaffold/config/core.rb +1 -1
  53. data/lib/active_scaffold/config/field_search.rb +9 -1
  54. data/lib/active_scaffold/config/form.rb +9 -1
  55. data/lib/active_scaffold/constraints.rb +22 -7
  56. data/lib/active_scaffold/core.rb +6 -10
  57. data/lib/active_scaffold/data_structures/action_columns.rb +0 -25
  58. data/lib/active_scaffold/data_structures/action_links.rb +1 -1
  59. data/lib/active_scaffold/data_structures/association/abstract.rb +8 -0
  60. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +8 -0
  61. data/lib/active_scaffold/data_structures/association/active_record.rb +1 -13
  62. data/lib/active_scaffold/data_structures/association/mongoid.rb +21 -8
  63. data/lib/active_scaffold/data_structures/column.rb +139 -28
  64. data/lib/active_scaffold/data_structures/columns.rb +12 -12
  65. data/lib/active_scaffold/data_structures/nested_info.rb +12 -0
  66. data/lib/active_scaffold/data_structures/sorting.rb +1 -1
  67. data/lib/active_scaffold/engine.rb +15 -1
  68. data/lib/active_scaffold/extensions/action_view_rendering.rb +13 -5
  69. data/lib/active_scaffold/extensions/cow_proxy.rb +1 -1
  70. data/lib/active_scaffold/extensions/routing_mapper.rb +1 -0
  71. data/lib/active_scaffold/extensions/unsaved_record.rb +9 -3
  72. data/lib/active_scaffold/finder.rb +147 -28
  73. data/lib/active_scaffold/helpers/action_link_helpers.rb +1 -1
  74. data/lib/active_scaffold/helpers/controller_helpers.rb +9 -4
  75. data/lib/active_scaffold/helpers/form_column_helpers.rb +153 -107
  76. data/lib/active_scaffold/helpers/human_condition_helpers.rb +48 -14
  77. data/lib/active_scaffold/helpers/list_column_helpers.rb +37 -20
  78. data/lib/active_scaffold/helpers/search_column_helpers.rb +137 -55
  79. data/lib/active_scaffold/helpers/show_column_helpers.rb +6 -6
  80. data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
  81. data/lib/active_scaffold/orm_checks.rb +21 -1
  82. data/lib/active_scaffold/registry.rb +10 -15
  83. data/lib/active_scaffold/tableless.rb +10 -79
  84. data/lib/active_scaffold/version.rb +2 -2
  85. data/lib/active_scaffold.rb +3 -9
  86. data/lib/generators/active_scaffold/install_generator.rb +2 -2
  87. data/test/bridges/bridge_test.rb +1 -1
  88. data/test/bridges/date_picker_test.rb +3 -2
  89. data/test/bridges/paperclip_test.rb +18 -14
  90. data/test/bridges/tiny_mce_test.rb +5 -3
  91. data/test/config/base_test.rb +1 -1
  92. data/test/config/core_test.rb +1 -1
  93. data/test/config/create_test.rb +1 -1
  94. data/test/config/delete_test.rb +1 -1
  95. data/test/config/field_search_test.rb +1 -1
  96. data/test/config/list_test.rb +1 -1
  97. data/test/config/nested_test.rb +1 -1
  98. data/test/config/search_test.rb +1 -1
  99. data/test/config/show_test.rb +1 -1
  100. data/test/config/subform_test.rb +1 -1
  101. data/test/config/update_test.rb +1 -1
  102. data/test/data_structures/action_columns_test.rb +1 -1
  103. data/test/data_structures/action_link_test.rb +1 -1
  104. data/test/data_structures/action_links_test.rb +1 -1
  105. data/test/data_structures/actions_test.rb +1 -1
  106. data/test/data_structures/association_column_test.rb +1 -1
  107. data/test/data_structures/column_test.rb +1 -1
  108. data/test/data_structures/columns_test.rb +1 -1
  109. data/test/data_structures/set_test.rb +1 -1
  110. data/test/data_structures/sorting_test.rb +1 -1
  111. data/test/data_structures/standard_column_test.rb +1 -1
  112. data/test/data_structures/validation_reflection_test.rb +1 -1
  113. data/test/data_structures/virtual_column_test.rb +1 -1
  114. data/test/extensions/active_record_test.rb +1 -1
  115. data/test/helpers/form_column_helpers_test.rb +7 -5
  116. data/test/helpers/pagination_helpers_test.rb +1 -1
  117. data/test/helpers/search_column_helpers_test.rb +2 -1
  118. data/test/misc/active_record_permissions_test.rb +1 -1
  119. data/test/misc/attribute_params_test.rb +1 -1
  120. data/test/misc/calculation_test.rb +1 -1
  121. data/test/misc/configurable_test.rb +1 -1
  122. data/test/misc/constraints_test.rb +2 -1
  123. data/test/misc/convert_numbers_format_test.rb +1 -1
  124. data/test/misc/finder_test.rb +39 -1
  125. data/test/misc/lang_test.rb +1 -1
  126. data/test/misc/parse_datetime_test.rb +1 -1
  127. data/test/misc/tableless_test.rb +1 -1
  128. data/test/test_helper.rb +4 -4
  129. metadata +5 -17
  130. data/config/brakeman.ignore +0 -26
  131. data/config/brakeman.yml +0 -3
  132. data/config/i18n-tasks.yml +0 -121
  133. data/lib/active_scaffold/bridges/shared/date_bridge.rb +0 -221
  134. data/lib/active_scaffold/delayed_setup.rb +0 -41
  135. data/lib/active_scaffold/extensions/left_outer_joins.rb +0 -43
@@ -40,14 +40,27 @@ module ActiveScaffold::DataStructures
40
40
  # the display-name of the column. this will be used, for instance, as the column title in the table and as the field name in the form.
41
41
  # if left alone it will utilize human_attribute_name which includes localization
42
42
  attr_writer :label
43
- def label
44
- as_(@label) || active_record_class.human_attribute_name(name.to_s)
43
+ def label(record = nil, scope = nil)
44
+ if @label.respond_to?(:call)
45
+ if record
46
+ @label.call(record, self, scope)
47
+ else
48
+ # sometimes label is called without a record in context (ie, from table
49
+ # headers). In this case fall back to the humanized attribute name
50
+ # instead of the Proc
51
+ active_record_class.human_attribute_name(name.to_s)
52
+ end
53
+ else
54
+ as_(@label) || active_record_class.human_attribute_name(name.to_s)
55
+ end
45
56
  end
46
57
 
47
58
  # a textual description of the column and its contents. this will be displayed with any associated form input widget, so you may want to consider adding a content example.
48
59
  attr_writer :description
49
- def description
50
- if @description
60
+ def description(record = nil, scope = nil)
61
+ if @description&.respond_to?(:call)
62
+ @description.call(record, self, scope)
63
+ elsif @description
51
64
  @description
52
65
  else
53
66
  I18n.t name, :scope => [:activerecord, :description, active_record_class.to_s.underscore.to_sym], :default => ''
@@ -87,6 +100,19 @@ module ActiveScaffold::DataStructures
87
100
  cattr_accessor :send_form_on_update_column, instance_accessor: false
88
101
  attr_accessor :send_form_on_update_column
89
102
 
103
+ # add a custom attr_accessor that can contain a Proc (or boolean or symbol)
104
+ # that will be called when the column renders, such that we can dynamically
105
+ # hide or show the column with an element that can be replaced by
106
+ # update_columns, but won't affect the form submission.
107
+ # The value can be set in the scaffold controller as follows to dynamically
108
+ # hide the column based on a Proc's output:
109
+ # config.columns[:my_column].hide_form_column_if = Proc.new { |record, column, scope| record.vehicle_type == 'tractor' }
110
+ # OR to always hide the column:
111
+ # config.columns[:my_column].hide_form_column_if = true
112
+ # OR to call a method on the record to determine whether to hide the column:
113
+ # config.columns[:my_column].hide_form_column_if = :hide_tractor_fields?
114
+ attr_accessor :hide_form_column_if
115
+
90
116
  # sorting on a column can be configured four ways:
91
117
  # sort = true default, uses intelligent sorting sql default
92
118
  # sort = false sometimes sorting doesn't make sense
@@ -118,24 +144,58 @@ module ActiveScaffold::DataStructures
118
144
  # supported options:
119
145
  # * for association columns
120
146
  # * :select - displays a simple <select> or a collection of checkboxes to (dis)associate records
121
- attr_accessor :form_ui
147
+ attr_reader :form_ui
148
+
149
+ attr_reader :form_ui_options
122
150
 
123
- attr_writer :list_ui
151
+ # value must be a Symbol, or an Array of form_ui and options hash which will be used with form_ui only
152
+ def form_ui=(value)
153
+ check_valid_action_ui_params(value)
154
+ @form_ui, @form_ui_options = *value
155
+ end
156
+
157
+ # value must be a Symbol, or an Array of list_ui and options hash which will be used with list_ui only
158
+ def list_ui=(value)
159
+ check_valid_action_ui_params(value)
160
+ @list_ui, @list_ui_options = *value
161
+ end
124
162
 
125
163
  def list_ui
126
164
  @list_ui || form_ui
127
165
  end
128
166
 
129
- attr_writer :show_ui
167
+ def list_ui_options
168
+ @list_ui ? @list_ui_options : form_ui_options
169
+ end
170
+
171
+ # value must be a Symbol, or an Array of show_ui and options hash which will be used with show_ui only
172
+ def show_ui=(value)
173
+ check_valid_action_ui_params(value)
174
+ @show_ui, @show_ui_options = *value
175
+ end
176
+
130
177
  def show_ui
131
178
  @show_ui || list_ui
132
179
  end
133
180
 
134
- attr_writer :search_ui
181
+ def show_ui_options
182
+ @show_ui ? @show_ui_options : list_ui_options
183
+ end
184
+
185
+ # value must be a Symbol, or an Array of search_ui and options hash which will be used with search_ui only
186
+ def search_ui=(value)
187
+ check_valid_action_ui_params(value)
188
+ @search_ui, @search_ui_options = *value
189
+ end
190
+
135
191
  def search_ui
136
192
  @search_ui || @form_ui || (:select if association && !association.polymorphic?)
137
193
  end
138
194
 
195
+ def search_ui_options
196
+ @search_ui ? @search_ui_options : form_ui_options
197
+ end
198
+
139
199
  # a place to store dev's column specific options
140
200
  attr_writer :options
141
201
  def options
@@ -314,6 +374,9 @@ module ActiveScaffold::DataStructures
314
374
  @name = name.to_sym
315
375
  @active_record_class = active_record_class
316
376
  @column = _columns_hash[name.to_s]
377
+ if @column.nil? && active_record? && active_record_class._default_attributes.key?(name.to_s)
378
+ @column = active_record_class._default_attributes[name.to_s]
379
+ end
317
380
  @delegated_association = delegated_association
318
381
  @cache_key = [@active_record_class.name, name].compact.map(&:to_s).join('#')
319
382
  setup_association_info
@@ -328,24 +391,9 @@ module ActiveScaffold::DataStructures
328
391
  @actions_for_association_links = self.class.actions_for_association_links.dup if association
329
392
  @select_columns = default_select_columns
330
393
 
331
- @text = @column.nil? || [:string, :text, String].include?(column_type)
394
+ @text = @column.nil? || [:string, :text, :citext, String].include?(column_type)
332
395
  @number = false
333
- if @column
334
- if active_record_class.respond_to?(:defined_enums) && active_record_class.defined_enums[name.to_s]
335
- @form_ui = :select
336
- @options = {:options => active_record_class.send(name.to_s.pluralize).keys.map(&:to_sym)}
337
- elsif column_number?
338
- @number = true
339
- @form_ui = :number
340
- @options = {:format => :i18n_number}
341
- else
342
- @form_ui =
343
- case @column.type
344
- when :boolean then :checkbox
345
- when :text then :textarea
346
- end
347
- end
348
- end
396
+ setup_defaults_for_column if @column
349
397
  @allow_add_existing = true
350
398
  @form_ui = self.class.association_form_ui if @association && self.class.association_form_ui
351
399
 
@@ -370,7 +418,7 @@ module ActiveScaffold::DataStructures
370
418
  # just the field (not table.field)
371
419
  def field_name
372
420
  return nil if virtual?
373
- @field_name ||= column ? quoted_field_name(column.name) : association.foreign_key
421
+ @field_name ||= column ? quoted_field_name(column.name) : quoted_field_name(association.foreign_key)
374
422
  end
375
423
 
376
424
  def <=>(other)
@@ -404,7 +452,22 @@ module ActiveScaffold::DataStructures
404
452
  end
405
453
 
406
454
  def default_for_empty_value
407
- (column.null ? nil : column.default) if column
455
+ return nil unless column
456
+ if column.is_a?(ActiveModel::Attribute)
457
+ column.value
458
+ elsif active_record?
459
+ null? ? nil : column.default
460
+ elsif mongoid?
461
+ column.default_val
462
+ end
463
+ end
464
+
465
+ def null?
466
+ if active_record? && !column.is_a?(ActiveModel::Attribute)
467
+ column&.null
468
+ else
469
+ true
470
+ end
408
471
  end
409
472
 
410
473
  # the table.field name for this column, if applicable
@@ -412,6 +475,10 @@ module ActiveScaffold::DataStructures
412
475
  @field ||= quoted_field(field_name)
413
476
  end
414
477
 
478
+ def quoted_foreign_type
479
+ quoted_field(quoted_field_name(association.foreign_type))
480
+ end
481
+
415
482
  def type_for_attribute
416
483
  ActiveScaffold::OrmChecks.type_for_attribute active_record_class, name
417
484
  end
@@ -420,8 +487,39 @@ module ActiveScaffold::DataStructures
420
487
  ActiveScaffold::OrmChecks.column_type active_record_class, name
421
488
  end
422
489
 
490
+ def default_value
491
+ ActiveScaffold::OrmChecks.column_type active_record_class, name
492
+ end
493
+
494
+ def attributes=(opts)
495
+ opts.each do |setting, value|
496
+ send "#{setting}=", value
497
+ end
498
+ end
499
+
500
+ def cast(value)
501
+ ActiveScaffold::OrmChecks.cast active_record_class, name, value
502
+ end
503
+
423
504
  protected
424
505
 
506
+ def setup_defaults_for_column
507
+ if active_record_class.respond_to?(:defined_enums) && active_record_class.defined_enums[name.to_s]
508
+ @form_ui = :select
509
+ @options = {:options => active_record_class.send(name.to_s.pluralize).keys.map(&:to_sym)}
510
+ elsif column_number?
511
+ @number = true
512
+ @form_ui = :number
513
+ @options = {:format => :i18n_number}
514
+ else
515
+ @form_ui =
516
+ case column_type
517
+ when :boolean then null? ? :boolean : :checkbox
518
+ when :text then :textarea
519
+ end
520
+ end
521
+ end
522
+
425
523
  def setup_association_info
426
524
  assoc = active_record_class.reflect_on_association(name)
427
525
  @association =
@@ -480,7 +578,7 @@ module ActiveScaffold::DataStructures
480
578
  end
481
579
 
482
580
  def column_number?
483
- return %i[float decimal integer].include? @column.type if active_record?
581
+ return %i[float decimal integer].include? column_type if active_record?
484
582
  return @column.type < Numeric if mongoid?
485
583
  end
486
584
 
@@ -534,5 +632,18 @@ module ActiveScaffold::DataStructures
534
632
  300
535
633
  end
536
634
  end
635
+
636
+ def check_valid_action_ui_params(value)
637
+ return true if valid_action_ui_params?(value)
638
+ raise ArgumentError, 'value must be a Symbol, or an array of Symbol and Hash'
639
+ end
640
+
641
+ def valid_action_ui_params?(value)
642
+ if value.is_a?(Array)
643
+ value.size <= 2 && value[0].is_a?(Symbol) && (value[1].nil? || value[1].is_a?(Hash))
644
+ else
645
+ value.nil? || value.is_a?(Symbol)
646
+ end
647
+ end
537
648
  end
538
649
  end
@@ -13,7 +13,7 @@ module ActiveScaffold::DataStructures
13
13
  # IT IS NOT MEANT FOR PUBLIC USE (but if you know what you're doing, go ahead)
14
14
  def _inheritable=(value)
15
15
  @sorted = true
16
- @_inheritable = value
16
+ @_inheritable = ::Set.new(value)
17
17
  end
18
18
 
19
19
  # This accessor is used by ActionColumns to create new Column objects without adding them to this set
@@ -21,8 +21,8 @@ module ActiveScaffold::DataStructures
21
21
 
22
22
  def initialize(active_record_class, *args)
23
23
  @active_record_class = active_record_class
24
- @_inheritable = []
25
- @set = []
24
+ @_inheritable = ::Set.new
25
+ @set = {}
26
26
  @sorted = nil
27
27
 
28
28
  add(*args)
@@ -35,9 +35,11 @@ module ActiveScaffold::DataStructures
35
35
  args = args.collect(&:to_sym)
36
36
 
37
37
  # make the columns inheritable
38
- @_inheritable.concat(args)
38
+ @_inheritable.merge(args)
39
39
  # then add columns to @set (unless they already exist)
40
- args.each { |a| @set << ActiveScaffold::DataStructures::Column.new(a.to_sym, @active_record_class) unless find_by_name(a) }
40
+ args.each do |a|
41
+ @set[a.to_sym] = ActiveScaffold::DataStructures::Column.new(a, @active_record_class) unless find_by_name(a)
42
+ end
41
43
  end
42
44
  alias << add
43
45
 
@@ -55,7 +57,7 @@ module ActiveScaffold::DataStructures
55
57
  klass = column.association.klass
56
58
  columns.each do |col|
57
59
  next if find_by_name col
58
- @set << ActiveScaffold::DataStructures::Column.new(col, klass, column.association)
60
+ @set[col.to_sym] = ActiveScaffold::DataStructures::Column.new(col, klass, column.association)
59
61
  end
60
62
  end
61
63
 
@@ -66,24 +68,22 @@ module ActiveScaffold::DataStructures
66
68
 
67
69
  # returns an array of columns with the provided names
68
70
  def find_by_names(*names)
69
- @set.find_all { |column| names.include? column.name }
71
+ names.map { |name| find_by_name name }
70
72
  end
71
73
 
72
74
  # returns the column of the given name.
73
75
  def find_by_name(name)
74
- # this works because of `def column.=='
75
- column = @set.find { |c| c == name }
76
- column
76
+ @set[name.to_sym]
77
77
  end
78
78
  alias [] find_by_name
79
79
 
80
80
  def each
81
- @set.each { |i| yield i }
81
+ @set.each_value { |name| yield name }
82
82
  end
83
83
 
84
84
  def _inheritable
85
85
  if @sorted
86
- @_inheritable
86
+ @_inheritable.to_a
87
87
  else
88
88
  @_inheritable.sort do |a, b|
89
89
  self[a] <=> self[b]
@@ -70,6 +70,10 @@ module ActiveScaffold::DataStructures
70
70
  def match_model?(model)
71
71
  false
72
72
  end
73
+
74
+ def create_with_parent?
75
+ false
76
+ end
73
77
  end
74
78
 
75
79
  class NestedInfoAssociation < NestedInfo
@@ -104,6 +108,14 @@ module ActiveScaffold::DataStructures
104
108
  association.through_singular? && source_reflection.reverse
105
109
  end
106
110
 
111
+ def create_with_parent?
112
+ if has_many? && !association.through?
113
+ false
114
+ elsif child_association || create_through_singular?
115
+ true
116
+ end
117
+ end
118
+
107
119
  def source_reflection
108
120
  @source_reflection ||= ActiveScaffold::DataStructures::Association::ActiveRecord.new(association.source_reflection)
109
121
  end
@@ -41,7 +41,7 @@ module ActiveScaffold::DataStructures
41
41
  column = get_column(column_name)
42
42
  raise ArgumentError, "Could not find column #{column_name}" if column.nil?
43
43
  raise ArgumentError, 'Sorting direction unknown' unless %i[ASC DESC].include? direction.to_sym
44
- @clauses << [column, direction.untaint] if column.sortable?
44
+ @clauses << [column, direction] if column.sortable?
45
45
  raise ArgumentError, "Can't mix :method- and :sql-based sorting" if mixed_sorting?
46
46
  end
47
47
 
@@ -2,8 +2,10 @@ module ActiveScaffold
2
2
  class Engine < ::Rails::Engine
3
3
  initializer 'active_scaffold.action_controller' do
4
4
  ActiveSupport.on_load :action_controller do
5
+ require 'active_scaffold/extensions/action_controller_rescueing'
6
+ require 'active_scaffold/extensions/action_controller_rendering'
7
+ require 'active_scaffold/extensions/routing_mapper'
5
8
  include ActiveScaffold::Core
6
- include ActiveScaffold::DelayedSetup if ActiveScaffold.delayed_setup
7
9
  include ActiveScaffold::RespondsToParent
8
10
  include ActiveScaffold::Helpers::ControllerHelpers
9
11
  include ActiveScaffold::ActiveRecordPermissions::ModelUserAccess::Controller
@@ -13,12 +15,17 @@ module ActiveScaffold
13
15
 
14
16
  initializer 'active_scaffold.action_view' do
15
17
  ActiveSupport.on_load :action_view do
18
+ require 'active_scaffold/extensions/action_view_rendering'
19
+ require 'active_scaffold/extensions/name_option_for_datetime'
16
20
  include ActiveScaffold::Helpers::ViewHelpers
17
21
  end
18
22
  end
19
23
 
20
24
  initializer 'active_scaffold.active_record' do
21
25
  ActiveSupport.on_load :active_record do
26
+ require 'active_scaffold/extensions/to_label'
27
+ require 'active_scaffold/extensions/unsaved_associated'
28
+ require 'active_scaffold/extensions/unsaved_record'
22
29
  include ActiveScaffold::ActiveRecordPermissions::ModelUserAccess::Model
23
30
  module ActiveRecord::Associations
24
31
  Association.send :include, ActiveScaffold::Tableless::Association
@@ -40,5 +47,12 @@ module ActiveScaffold
40
47
  initializer 'active_scaffold.assets' do
41
48
  config.assets.precompile << 'active_scaffold/indicator.gif'
42
49
  end
50
+
51
+ initializer 'active_scaffold.extensions' do
52
+ require 'active_scaffold/extensions/cow_proxy'
53
+ require 'active_scaffold/extensions/ice_nine'
54
+ require 'active_scaffold/extensions/localize'
55
+ require 'active_scaffold/extensions/paginator_extensions'
56
+ end
43
57
  end
44
58
  end
@@ -119,6 +119,17 @@ module ActiveScaffold #:nodoc:
119
119
  end
120
120
  end
121
121
 
122
+ def remote_controller_config(controller_path)
123
+ # attempt to retrieve the active_scaffold_config by constantizing the controller path
124
+ "#{controller_path}_controller".camelize.constantize.active_scaffold_config
125
+ rescue NameError
126
+ # if we couldn't determine the controller config by instantiating the
127
+ # controller class, parse the ActiveRecord model name from the
128
+ # controller path, which might be a namespaced controller (e.g., 'admin/admins')
129
+ model = controller_path.to_s.sub(%r{.*/}, '').singularize
130
+ active_scaffold_config_for(model)
131
+ end
132
+
122
133
  def render_embedded(options)
123
134
  require 'digest/md5'
124
135
 
@@ -144,13 +155,10 @@ module ActiveScaffold #:nodoc:
144
155
  else
145
156
  url = url_for(url_options)
146
157
  content_tag(:div, :id => id, :class => 'active-scaffold-component', :data => {:refresh => url}) do
147
- # parse the ActiveRecord model name from the controller path, which
148
- # might be a namespaced controller (e.g., 'admin/admins')
149
- model = remote_controller.to_s.sub(%r{.*/}, '').singularize
150
158
  content_tag(:div, :class => 'active-scaffold-header') do
151
159
  content_tag(:h2) do
152
- link_label = options[:label] || active_scaffold_config_for(model).list.label
153
- link_to(link_label, url, remote: true, class: 'load-embedded', data: {error_msg: as_(:error_500)}) <<
160
+ label = options[:label] || remote_controller_config(remote_controller).list.label
161
+ link_to(label, url, remote: true, class: 'load-embedded', data: {error_msg: as_(:error_500)}) <<
154
162
  loading_indicator_tag(url_options)
155
163
  end
156
164
  end
@@ -49,7 +49,7 @@ module CowProxy
49
49
  class ActionLinks < ::CowProxy::WrapClass(::ActiveScaffold::DataStructures::ActionLinks)
50
50
  def method_missing(name, *args, &block)
51
51
  CowProxy.debug { "method missing #{name} in #{__getobj__.name}" }
52
- return super if name =~ /[!?]$/
52
+ return super if name.match?(/[!?]$/)
53
53
  subgroup =
54
54
  if _instance_variable_defined?("@#{name}")
55
55
  _instance_variable_get("@#{name}")
@@ -68,6 +68,7 @@ module ActiveScaffold
68
68
  end
69
69
  end
70
70
  end
71
+ ActiveSupport.run_load_hooks(:active_scaffold_routing, Routing)
71
72
  end
72
73
 
73
74
  module ActionDispatch
@@ -11,15 +11,21 @@ module ActiveScaffold::UnsavedRecord
11
11
  end
12
12
 
13
13
  # automatically unsets the unsaved flag
14
- def save(*)
14
+ def save(**)
15
15
  super.tap { self.unsaved = false }
16
16
  end
17
17
 
18
18
  def keeping_errors
19
19
  old_errors = errors.dup if errors.present?
20
20
  result = yield
21
- old_errors&.each do |attr|
22
- old_errors[attr].each { |msg| errors.add(attr, msg) unless errors.added?(attr, msg) }
21
+ old_errors&.each do |e|
22
+ if e.is_a?(String) || e.is_a?(Symbol)
23
+ # Rails <6.1 errors API.
24
+ old_errors[e].each { |msg| errors.add(e, msg) unless errors.added?(e, msg) }
25
+ else
26
+ # Rails >=6.1 errors API (https://code.lulalala.com/2020/0531-1013.html).
27
+ errors.add(e.attribute, e.message) unless errors.added?(e.attribute, e.message)
28
+ end
23
29
  end
24
30
  result && old_errors.blank?
25
31
  end