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
@@ -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