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
@@ -12,7 +12,10 @@ module ActiveScaffold::Actions
12
12
  def deleted
13
13
  query = PaperTrail::Version.destroys.where(:item_type => active_scaffold_config.model.name)
14
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)
15
+ foreign_key = nested.child_association.foreign_key
16
+ parent_id = nested.parent_id
17
+ parent_id = parent_id&.to_i if self.class.active_scaffold_config.columns[foreign_key]&.number?
18
+ query = query.where_object(foreign_key => parent_id)
16
19
  end
17
20
  pager = Paginator.new(query.count, active_scaffold_config.list.per_page) do |offset, per_page|
18
21
  query.offset(offset).limit(per_page).map(&:reify)
@@ -1,11 +1,11 @@
1
1
  module ActiveScaffold
2
2
  module Helpers
3
3
  module FormColumnHelpers
4
- def active_scaffold_input_paperclip(column, options)
4
+ def active_scaffold_input_paperclip(column, options, ui_options: column.options)
5
5
  record = options[:object]
6
6
  paperclip = record.send(column.name.to_s)
7
- content = active_scaffold_column_paperclip(record, column) if paperclip.file?
8
- active_scaffold_file_with_remove_link(column, options, content, 'delete_', 'paperclip_controls')
7
+ content = active_scaffold_column_paperclip(record, column, ui_options: ui_options) if paperclip.file?
8
+ active_scaffold_file_with_remove_link(column, options, content, 'delete_', 'paperclip_controls', ui_options: ui_options)
9
9
  end
10
10
  end
11
11
  end
@@ -1,7 +1,7 @@
1
1
  module ActiveScaffold
2
2
  module Helpers
3
3
  module ListColumnHelpers
4
- def active_scaffold_column_paperclip(record, column)
4
+ def active_scaffold_column_paperclip(record, column, ui_options: column.options)
5
5
  paperclip = record.send(column.name.to_s)
6
6
  return nil unless paperclip.file?
7
7
  content =
@@ -10,21 +10,21 @@ class ActiveScaffold::Bridges::RecordSelect
10
10
 
11
11
  module FormColumnHelpers
12
12
  # requires RecordSelect plugin to be installed and configured.
13
- def active_scaffold_input_record_select(column, options)
13
+ def active_scaffold_input_record_select(column, options, ui_options: column.options)
14
14
  record = options.delete(:object)
15
15
  if column.association&.singular?
16
- multiple = column.options.dig(:html_options, :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]
16
+ multiple = ui_options.dig(:html_options, :multiple)
17
+ html = active_scaffold_record_select(record, column, options, record.send(column.name), multiple, ui_options: ui_options)
18
+ html << active_scaffold_new_record_subform(column, record, options, ui_options: ui_options) if ui_options[:add_new]
19
19
  html
20
20
  elsif column.association&.collection?
21
- active_scaffold_record_select(record, column, options, record.send(column.name), true)
21
+ active_scaffold_record_select(record, column, options, record.send(column.name), true, ui_options: ui_options)
22
22
  else
23
- active_scaffold_record_select_autocomplete(record, column, options)
23
+ active_scaffold_record_select_autocomplete(record, column, options, ui_options: ui_options)
24
24
  end
25
25
  end
26
26
 
27
- def active_scaffold_record_select(record, column, options, value, multiple)
27
+ def active_scaffold_record_select(record, column, options, value, multiple, ui_options: column.options)
28
28
  unless column.association
29
29
  raise ArgumentError, "record_select can only work against associations (and #{column.name} is not). "\
30
30
  'A common mistake is to specify the foreign key field (like :user_id), instead of the association (:user).'
@@ -43,7 +43,7 @@ class ActiveScaffold::Bridges::RecordSelect
43
43
  record_select_options = active_scaffold_input_text_options(options).merge(
44
44
  :controller => remote_controller
45
45
  )
46
- record_select_options.merge!(column.options)
46
+ record_select_options.merge!(ui_options)
47
47
 
48
48
  html =
49
49
  if multiple
@@ -51,29 +51,29 @@ class ActiveScaffold::Bridges::RecordSelect
51
51
  else
52
52
  record_select_field(options[:name], value || klass.new, record_select_options)
53
53
  end
54
- html = self.class.field_error_proc.call(html, self) if record.errors[column.name].any?
54
+ html = instance_exec(html, self, &self.class.field_error_proc) if record.errors[column.name].any?
55
55
  html
56
56
  end
57
57
 
58
- def active_scaffold_record_select_autocomplete(record, column, options)
58
+ def active_scaffold_record_select_autocomplete(record, column, options, ui_options: column.options)
59
59
  record_select_options = active_scaffold_input_text_options(options).reverse_merge(
60
60
  :controller => active_scaffold_controller_for(record.class).controller_path
61
- ).merge(column.options)
61
+ ).merge(ui_options)
62
62
  html = record_select_autocomplete(options[:name], record, record_select_options)
63
- html = self.class.field_error_proc.call(html, self) if record.errors[column.name].any?
63
+ html = instance_exec(html, self, &self.class.field_error_proc) if record.errors[column.name].any?
64
64
  html
65
65
  end
66
66
  end
67
67
 
68
68
  module SearchColumnHelpers
69
- def active_scaffold_search_record_select(column, options)
70
- value = field_search_record_select_value(column, options[:value])
71
- active_scaffold_record_select(options[:object], column, options, value, column.options[:multiple])
69
+ def active_scaffold_search_record_select(column, options, ui_options: column.options)
70
+ value = field_search_record_select_value(column, options[:value], ui_options: ui_options)
71
+ active_scaffold_record_select(options[:object], column, options, value, ui_options[:multiple], ui_options: ui_options)
72
72
  end
73
73
 
74
- def field_search_record_select_value(column, value)
74
+ def field_search_record_select_value(column, value, ui_options: column.options)
75
75
  return if value.blank?
76
- if column.options[:multiple]
76
+ if ui_options[:multiple]
77
77
  column.association.klass.find value.collect!(&:to_i)
78
78
  else
79
79
  column.association.klass.find(value.to_i)
@@ -14,16 +14,16 @@ class ActiveScaffold::Bridges::TinyMce
14
14
  # but not the plugins, toolbars etc.
15
15
  # The other one is :tinymce_config, which selects the config to use from tinymce.yml.
16
16
  # See the tinymce-rails gem documentation for usage.
17
- def active_scaffold_input_text_editor(column, options)
18
- options[:class] = "#{options[:class]} mceEditor #{column.options[:class]}".strip
17
+ def active_scaffold_input_text_editor(column, options, ui_options: column.options)
18
+ options[:class] = "#{options[:class]} mceEditor #{ui_options[:class]}".strip
19
19
 
20
- settings = tinymce_configuration(column.options[:tinymce_config] || :default).options
21
- .reject { |k, _v| k == 'selector' }
22
- .merge(column.options[:tinymce] || {})
20
+ settings = tinymce_configuration(ui_options[:tinymce_config] || :default).options
21
+ .reject { |k, _v| k == 'selector' }
22
+ .merge(ui_options[:tinymce] || {})
23
23
  options['data-tinymce'] = settings.to_json if ActiveScaffold.js_framework != :prototype
24
24
 
25
25
  html = []
26
- html << send(override_input(:textarea), column, options)
26
+ html << send(override_input(:textarea), column, options, ui_options: ui_options)
27
27
  if ActiveScaffold.js_framework == :prototype && (request.xhr? || params[:iframe])
28
28
  html << javascript_tag("tinyMCE.settings = #{settings.to_json}; tinyMCE.execCommand('mceAddEditor', false, '#{options[:id]}');")
29
29
  end
@@ -11,7 +11,7 @@ class ActiveScaffold::Bridges::TinyMce < ActiveScaffold::DataStructures::Bridge
11
11
  def self.javascripts
12
12
  case ActiveScaffold.js_framework
13
13
  when :jquery
14
- ['tinymce-jquery', 'jquery/tiny_mce_bridge']
14
+ ['tinymce', 'jquery/tiny_mce_bridge']
15
15
  when :prototype
16
16
  ['tinymce', 'prototype/tiny_mce_bridge']
17
17
  end
@@ -1,13 +1,8 @@
1
1
  module ActiveScaffold::Bridges
2
2
  class UsaStateSelect
3
3
  module UsaStateSelectHelpers
4
- def usa_state_select_options(options)
5
- # TODO: remove when rails 3.2 support is dropped
6
- defined?(ActionView::Helpers::InstanceTag) ? options[:object] : options
7
- end
8
-
9
4
  def usa_state_select(object, method, priority_states = nil, options = {}, html_options = {})
10
- ActionView::Helpers::Tags::UsaStateSelect.new(object, method, self, usa_state_select_options(options)).to_usa_state_select_tag(priority_states, options, html_options)
5
+ ActionView::Helpers::Tags::UsaStateSelect.new(object, method, self, options).to_usa_state_select_tag(priority_states, options, html_options)
11
6
  end
12
7
  end
13
8
 
@@ -63,18 +58,18 @@ module ActiveScaffold::Bridges
63
58
  end
64
59
 
65
60
  module FormColumnHelpers
66
- def active_scaffold_input_usa_state(column, options)
61
+ def active_scaffold_input_usa_state(column, options, ui_options: column.options)
67
62
  select_options = {:prompt => as_(:_select_)}
68
63
  select_options.merge!(options)
69
- options.reverse_merge!(column.options).except!(:prompt, :priority)
64
+ options.reverse_merge!(ui_options).except!(:prompt, :priority)
70
65
  active_scaffold_select_name_with_multiple options
71
- usa_state_select(:record, column.name, column.options[:priority], select_options, options.except(:object))
66
+ usa_state_select(:record, column.name, ui_options[:priority], select_options, options.except(:object))
72
67
  end
73
68
  end
74
69
 
75
70
  module SearchColumnHelpers
76
- def active_scaffold_search_usa_state(column, options)
77
- active_scaffold_input_usa_state(column, options.merge!(:selected => options.delete(:value)))
71
+ def active_scaffold_search_usa_state(column, options, ui_options: column.options)
72
+ active_scaffold_input_usa_state(column, options.merge!(:selected => options.delete(:value)), ui_options: ui_options)
78
73
  end
79
74
  end
80
75
  end
@@ -1,9 +1,6 @@
1
1
  module ActiveScaffold
2
2
  module Bridges
3
3
  ActiveScaffold.autoload_subdir('bridges', self)
4
- module Shared
5
- autoload :DateBridge, 'active_scaffold/bridges/shared/date_bridge'
6
- end
7
4
 
8
5
  mattr_accessor :bridges
9
6
  mattr_accessor :bridges_run
@@ -112,7 +112,7 @@ module ActiveScaffold::Config
112
112
  def columns=(val)
113
113
  @columns._inheritable = val.collect(&:to_sym)
114
114
  # Add virtual columns
115
- @columns << val.collect { |c| c.to_sym unless @columns[c.to_sym] }.compact
115
+ @columns.add(*val)
116
116
  end
117
117
 
118
118
  # lets you override the global ActiveScaffold frontend for a specific controller
@@ -7,6 +7,7 @@ module ActiveScaffold::Config
7
7
  super
8
8
  @text_search = self.class.text_search
9
9
  @human_conditions = self.class.human_conditions
10
+ @floating_footer = self.class.floating_footer
10
11
  end
11
12
 
12
13
  # global level configuration
@@ -29,6 +30,10 @@ module ActiveScaffold::Config
29
30
  cattr_accessor :human_conditions, instance_accessor: false
30
31
  @@human_conditions = false
31
32
 
33
+ # whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
34
+ class_attribute :floating_footer, instance_accessor: false
35
+ @@floating_footer = false
36
+
32
37
  # instance-level configuration
33
38
  # ----------------------------
34
39
 
@@ -71,8 +76,11 @@ module ActiveScaffold::Config
71
76
  # instead of just filtered you may show the user a humanized search condition statment
72
77
  attr_accessor :human_conditions
73
78
 
79
+ # whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
80
+ attr_accessor :floating_footer
81
+
74
82
  UserSettings.class_eval do
75
- user_attr :optional_columns, :group_options, :grouped_columns, :human_conditions
83
+ user_attr :optional_columns, :group_options, :grouped_columns, :human_conditions, :floating_footer
76
84
  end
77
85
  end
78
86
  end
@@ -5,6 +5,7 @@ module ActiveScaffold::Config
5
5
  @show_unauthorized_columns = self.class.show_unauthorized_columns
6
6
  @refresh_list = self.class.refresh_list
7
7
  @persistent = self.class.persistent
8
+ @floating_footer = self.class.floating_footer
8
9
 
9
10
  # no global setting here because multipart should only be set for specific forms
10
11
  @multipart = false
@@ -23,6 +24,10 @@ module ActiveScaffold::Config
23
24
  class_attribute :refresh_list, instance_accessor: false
24
25
  @@refresh_list = false
25
26
 
27
+ # whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
28
+ class_attribute :floating_footer, instance_accessor: false
29
+ @@floating_footer = false
30
+
26
31
  # instance-level configuration
27
32
  # ----------------------------
28
33
 
@@ -41,6 +46,9 @@ module ActiveScaffold::Config
41
46
  # whether we should refresh list after create or not
42
47
  attr_accessor :refresh_list
43
48
 
49
+ # whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
50
+ attr_accessor :floating_footer
51
+
44
52
  columns_accessor :columns do
45
53
  columns.exclude :created_on, :created_at, :updated_on, :updated_at, :as_marked
46
54
  columns.exclude(*@core.columns.collect { |c| c.name if c.association&.polymorphic? }.compact)
@@ -53,7 +61,7 @@ module ActiveScaffold::Config
53
61
  end
54
62
 
55
63
  UserSettings.class_eval do
56
- user_attr :persistent, :refresh_list, :show_unauthorized_columns
64
+ user_attr :persistent, :refresh_list, :show_unauthorized_columns, :floating_footer
57
65
 
58
66
  attr_writer :multipart
59
67
  def multipart?
@@ -11,13 +11,27 @@ module ActiveScaffold
11
11
  @active_scaffold_constraints ||= active_scaffold_embedded_params[:constraints] || {}
12
12
  end
13
13
 
14
+ def register_constraint?(column_name, value)
15
+ if params_hash?(value)
16
+ false
17
+ elsif value.is_a?(Array)
18
+ column = active_scaffold_config.columns[column_name]
19
+ column && value.size > (column.association&.polymorphic? ? 2 : 1)
20
+ else
21
+ true
22
+ end
23
+ end
24
+
14
25
  # For each enabled action, adds the constrained columns to the ActionColumns object (if it exists).
15
26
  # This lets the ActionColumns object skip constrained columns.
16
27
  #
17
- # If the constraint value is a Hash, then we assume the constraint is a multi-level association constraint (the reverse of a has_many :through) and we do NOT register the constraint column.
28
+ # If the constraint value is a Hash, then we assume the constraint is a multi-level association constraint
29
+ # (the reverse of a has_many :through) and we do NOT register the constraint column.
30
+ # If the constraint value is an Array, or Array with more than 2 items for polymorphic column,
31
+ # we do NOT register the constraint column, as records will have different values in the column.
18
32
  def register_constraints_with_action_columns(constrained_fields = nil)
19
33
  constrained_fields ||= []
20
- constrained_fields |= active_scaffold_constraints.reject { |_, v| params_hash?(v) }.keys.collect(&:to_sym)
34
+ constrained_fields |= active_scaffold_constraints.select { |k, v| register_constraint?(k, v) }.keys.collect(&:to_sym)
21
35
  exclude_actions = []
22
36
  %i[list update].each do |action_name|
23
37
  if active_scaffold_config.actions.include? action_name
@@ -111,10 +125,10 @@ module ActiveScaffold
111
125
  value = association.klass.find(value).send(association.primary_key) if association.primary_key
112
126
 
113
127
  if association.polymorphic?
114
- unless value.is_a?(Array) && value.size == 2
128
+ unless value.is_a?(Array) && value.size >= 2
115
129
  raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(association), caller
116
130
  end
117
- condition = {table => {association.foreign_type => value[0], field => value[1]}}
131
+ condition = {table => {association.foreign_type => value[0], field => value.size == 2 ? value[1] : value[1..-1]}}
118
132
  else
119
133
  condition = {table => {field.to_s => value}}
120
134
  end
@@ -149,11 +163,12 @@ module ActiveScaffold
149
163
  if column.association.collection?
150
164
  record.send(k.to_s).send(:<<, column.association.klass.find(v))
151
165
  elsif column.association.polymorphic?
152
- unless v.is_a?(Array) && v.size == 2
166
+ unless v.is_a?(Array) && v.size >= 2
153
167
  raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(column.association), caller
154
168
  end
155
- record.send("#{k}=", v[0].constantize.find(v[1]))
156
- elsif !column.association.source_reflection&.options&.include?(:through) # regular singular association, or one-level through association
169
+ record.send("#{k}=", v[0].constantize.find(v[1])) if v.size == 2
170
+ elsif !column.association.source_reflection&.options&.include?(:through) && # regular singular association, or one-level through association
171
+ !v.is_a?(Array)
157
172
  record.send("#{k}=", column.association.klass.find(v))
158
173
 
159
174
  # setting the belongs_to side of a has_one isn't safe. if the has_one was already
@@ -257,6 +257,8 @@ module ActiveScaffold
257
257
  def self.column_type_cast(value, column)
258
258
  if defined?(ActiveRecord) && column.is_a?(ActiveRecord::ConnectionAdapters::Column)
259
259
  active_record_column_type_cast(value, column)
260
+ elsif defined?(ActiveModel) && column.is_a?(ActiveModel::Attribute)
261
+ active_record_column_type_cast(value, column.type)
260
262
  elsif defined?(Mongoid) && column.is_a?(Mongoid::Fields::Standard)
261
263
  mongoid_column_type_cast(value, column)
262
264
  else
@@ -269,16 +271,10 @@ module ActiveScaffold
269
271
  column.type.evolve value
270
272
  end
271
273
 
272
- def self.active_record_column_type_cast(value, column)
273
- return Time.zone.at(value.to_i) if value =~ /\A\d+\z/ && %i[time datetime].include?(column.type)
274
- if Rails.version < '5.0'
275
- column.type_cast_from_user value
276
- elsif column.type.respond_to? :cast # jruby-jdbc and rails 5
277
- column.type.cast value
278
- else
279
- cast_type = ActiveRecord::Type.lookup column.type
280
- cast_type ? cast_type.cast(value) : value
281
- end
274
+ def self.active_record_column_type_cast(value, column_or_type)
275
+ return Time.zone.at(value.to_i) if value =~ /\A\d+\z/ && %i[time datetime].include?(column_or_type.type)
276
+ cast_type = column_or_type.is_a?(ActiveRecord::ConnectionAdapters::Column) ? ActiveRecord::Type.lookup(column_or_type.type) : column_or_type
277
+ cast_type ? cast_type.cast(value) : value
282
278
  end
283
279
  end
284
280
  end
@@ -98,31 +98,6 @@ module ActiveScaffold::DataStructures
98
98
  visible_columns(options.reverse_merge(flatten: true)).map(&:name)
99
99
  end
100
100
 
101
- def each(options = nil, &proc)
102
- if options
103
- ActiveSupport::Deprecation.warn 'use each_column'
104
- each_column(options, &proc)
105
- else
106
- super(&proc)
107
- end
108
- end
109
-
110
- def collect_visible(options = {}, &proc)
111
- ActiveSupport::Deprecation.warn "use visible_columns#{"(#{options.inspect})" if options.present?}#{'.map(&proc)' if proc}"
112
- columns = visible_columns(options)
113
- proc ? columns.map(&proc) : columns
114
- end
115
-
116
- def names
117
- ActiveSupport::Deprecation.warn 'use visible_columns.map(&:name)'
118
- visible_columns(flatten: true).map(&:name)
119
- end
120
-
121
- def names_without_auth_check
122
- ActiveSupport::Deprecation.warn 'use to_a'
123
- to_a
124
- end
125
-
126
101
  def action_name
127
102
  @action.user_settings_key
128
103
  end
@@ -144,7 +144,7 @@ module ActiveScaffold::DataStructures
144
144
  end
145
145
 
146
146
  def method_missing(name, *args, &block)
147
- return super if name =~ /[!?]$/
147
+ return super if name.match?(/[!?]$/)
148
148
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
149
149
  def #{name}(label = nil) # rubocop:disable Style/CommentedKeyword
150
150
  @#{name} ||= subgroup('#{name}'.to_sym, label)
@@ -54,6 +54,14 @@ module ActiveScaffold::DataStructures::Association
54
54
  through? && through_reflection.collection?
55
55
  end
56
56
 
57
+ def primary_key
58
+ @association.options[:primary_key]
59
+ end
60
+
61
+ def counter_cache
62
+ @association.options[:counter_cache]
63
+ end
64
+
57
65
  def polymorphic?
58
66
  false
59
67
  end
@@ -5,6 +5,14 @@ module ActiveScaffold::DataStructures::Association
5
5
  klass.am_relations.values
6
6
  end
7
7
 
8
+ def primary_key
9
+ @association[:primary_key]
10
+ end
11
+
12
+ def counter_cache
13
+ @association[:counter_cache]
14
+ end
15
+
8
16
  def inverse_klass
9
17
  as ? @association[:inverse_class_name].constantize : super
10
18
  end
@@ -30,14 +30,6 @@ module ActiveScaffold::DataStructures::Association
30
30
  @association.active_record
31
31
  end
32
32
 
33
- def primary_key
34
- @association.options[:primary_key]
35
- end
36
-
37
- def counter_cache
38
- @association.options[:counter_cache]
39
- end
40
-
41
33
  def as
42
34
  @association.options[:as]
43
35
  end
@@ -64,11 +56,7 @@ module ActiveScaffold::DataStructures::Association
64
56
  end
65
57
 
66
58
  def counter_cache_hack?
67
- if has_many?
68
- Rails.version < '5.0' && as
69
- elsif belongs_to?
70
- counter_cache && (Rails.version >= '5.0' || !polymorphic?)
71
- end
59
+ belongs_to? && counter_cache && Rails.version < '6.0'
72
60
  end
73
61
 
74
62
  protected
@@ -2,15 +2,28 @@ module ActiveScaffold::DataStructures::Association
2
2
  class Mongoid < Abstract
3
3
  delegate :inverse_klass, :as, :dependent, :inverse, to: :@association
4
4
 
5
+ def belongs_to?
6
+ # once Ruby 2.6 support is dropped, use macro_mapping? always
7
+ defined?(::Mongoid::Association) ? macro_mapping?(:belongs_to) : super
8
+ end
9
+
10
+ def has_one? # rubocop:disable Naming/PredicateName
11
+ defined?(::Mongoid::Association) ? macro_mapping?(:has_one) : super
12
+ end
13
+
14
+ def has_many? # rubocop:disable Naming/PredicateName
15
+ defined?(::Mongoid::Association) ? macro_mapping?(:has_many) : super
16
+ end
17
+
18
+ def habtm?
19
+ defined?(::Mongoid::Association) ? macro_mapping?(:has_and_belongs_to_many) : super
20
+ end
21
+
5
22
  # polymorphic belongs_to
6
23
  def polymorphic?
7
24
  belongs_to? && @association.polymorphic?
8
25
  end
9
26
 
10
- def primary_key
11
- @association[:primary_key]
12
- end
13
-
14
27
  def association_primary_key
15
28
  @association.primary_key
16
29
  end
@@ -19,10 +32,6 @@ module ActiveScaffold::DataStructures::Association
19
32
  @association.type
20
33
  end
21
34
 
22
- def counter_cache
23
- @association[:counter_cache]
24
- end
25
-
26
35
  def table_name
27
36
  @association.klass.collection.name
28
37
  end
@@ -38,5 +47,9 @@ module ActiveScaffold::DataStructures::Association
38
47
  def self.reflect_on_all_associations(klass)
39
48
  klass.relations.values
40
49
  end
50
+
51
+ def macro_mapping?(macro)
52
+ @association.is_a? ::Mongoid::Association::MACRO_MAPPING[macro]
53
+ end
41
54
  end
42
55
  end