active_scaffold 3.6.20 → 3.7.1

Sign up to get free protection for your applications and to get access to all the features.
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