active_scaffold 3.6.20 → 3.7.0

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +27 -0
  3. data/README.md +27 -16
  4. data/app/assets/javascripts/jquery/active_scaffold.js +38 -6
  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 +12 -1
  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/_render_field.js.erb +19 -11
  11. data/config/locales/ja.yml +59 -59
  12. data/lib/active_scaffold/actions/common_search.rb +2 -2
  13. data/lib/active_scaffold/actions/core.rb +30 -10
  14. data/lib/active_scaffold/actions/field_search.rb +9 -6
  15. data/lib/active_scaffold/actions/nested.rb +7 -7
  16. data/lib/active_scaffold/attribute_params.rb +19 -57
  17. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +0 -3
  18. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +1 -1
  19. data/lib/active_scaffold/bridges/active_storage.rb +3 -0
  20. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +2 -2
  21. data/lib/active_scaffold/bridges/date_picker/helper.rb +4 -4
  22. data/lib/active_scaffold/bridges/paper_trail/actions.rb +4 -1
  23. data/lib/active_scaffold/bridges/record_select/helpers.rb +2 -2
  24. data/lib/active_scaffold/bridges/tiny_mce.rb +1 -1
  25. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +1 -6
  26. data/lib/active_scaffold/config/core.rb +1 -1
  27. data/lib/active_scaffold/config/field_search.rb +9 -1
  28. data/lib/active_scaffold/config/form.rb +9 -1
  29. data/lib/active_scaffold/core.rb +2 -8
  30. data/lib/active_scaffold/data_structures/action_columns.rb +0 -25
  31. data/lib/active_scaffold/data_structures/action_links.rb +1 -1
  32. data/lib/active_scaffold/data_structures/association/abstract.rb +8 -0
  33. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +8 -0
  34. data/lib/active_scaffold/data_structures/association/active_record.rb +1 -13
  35. data/lib/active_scaffold/data_structures/association/mongoid.rb +21 -8
  36. data/lib/active_scaffold/data_structures/column.rb +31 -5
  37. data/lib/active_scaffold/data_structures/columns.rb +12 -12
  38. data/lib/active_scaffold/data_structures/nested_info.rb +12 -0
  39. data/lib/active_scaffold/data_structures/sorting.rb +1 -1
  40. data/lib/active_scaffold/engine.rb +0 -1
  41. data/lib/active_scaffold/extensions/action_view_rendering.rb +13 -5
  42. data/lib/active_scaffold/extensions/cow_proxy.rb +1 -1
  43. data/lib/active_scaffold/extensions/unsaved_record.rb +9 -3
  44. data/lib/active_scaffold/finder.rb +5 -1
  45. data/lib/active_scaffold/helpers/action_link_helpers.rb +1 -1
  46. data/lib/active_scaffold/helpers/form_column_helpers.rb +48 -22
  47. data/lib/active_scaffold/helpers/list_column_helpers.rb +3 -2
  48. data/lib/active_scaffold/helpers/search_column_helpers.rb +8 -2
  49. data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
  50. data/lib/active_scaffold/registry.rb +10 -15
  51. data/lib/active_scaffold/tableless.rb +10 -79
  52. data/lib/active_scaffold/version.rb +2 -2
  53. data/lib/active_scaffold.rb +0 -7
  54. data/lib/generators/active_scaffold/install_generator.rb +2 -2
  55. data/test/bridges/bridge_test.rb +1 -1
  56. data/test/bridges/paperclip_test.rb +16 -13
  57. data/test/bridges/tiny_mce_test.rb +1 -1
  58. data/test/config/base_test.rb +1 -1
  59. data/test/config/core_test.rb +1 -1
  60. data/test/config/create_test.rb +1 -1
  61. data/test/config/delete_test.rb +1 -1
  62. data/test/config/field_search_test.rb +1 -1
  63. data/test/config/list_test.rb +1 -1
  64. data/test/config/nested_test.rb +1 -1
  65. data/test/config/search_test.rb +1 -1
  66. data/test/config/show_test.rb +1 -1
  67. data/test/config/subform_test.rb +1 -1
  68. data/test/config/update_test.rb +1 -1
  69. data/test/data_structures/action_columns_test.rb +1 -1
  70. data/test/data_structures/action_link_test.rb +1 -1
  71. data/test/data_structures/action_links_test.rb +1 -1
  72. data/test/data_structures/actions_test.rb +1 -1
  73. data/test/data_structures/association_column_test.rb +1 -1
  74. data/test/data_structures/column_test.rb +1 -1
  75. data/test/data_structures/columns_test.rb +1 -1
  76. data/test/data_structures/set_test.rb +1 -1
  77. data/test/data_structures/sorting_test.rb +1 -1
  78. data/test/data_structures/standard_column_test.rb +1 -1
  79. data/test/data_structures/validation_reflection_test.rb +1 -1
  80. data/test/data_structures/virtual_column_test.rb +1 -1
  81. data/test/extensions/active_record_test.rb +1 -1
  82. data/test/helpers/pagination_helpers_test.rb +1 -1
  83. data/test/misc/active_record_permissions_test.rb +1 -1
  84. data/test/misc/attribute_params_test.rb +1 -1
  85. data/test/misc/calculation_test.rb +1 -1
  86. data/test/misc/configurable_test.rb +1 -1
  87. data/test/misc/constraints_test.rb +1 -1
  88. data/test/misc/convert_numbers_format_test.rb +1 -1
  89. data/test/misc/finder_test.rb +1 -1
  90. data/test/misc/lang_test.rb +1 -1
  91. data/test/misc/parse_datetime_test.rb +1 -1
  92. data/test/misc/tableless_test.rb +1 -1
  93. data/test/test_helper.rb +4 -4
  94. metadata +5 -13
  95. data/lib/active_scaffold/delayed_setup.rb +0 -41
  96. data/lib/active_scaffold/extensions/left_outer_joins.rb +0 -43
@@ -6,6 +6,7 @@ module ActiveScaffold::Actions
6
6
  before_action :check_input_device
7
7
  before_action :register_constraints_with_action_columns, :unless => :nested?
8
8
  after_action :clear_flashes
9
+ after_action :dl_cookie
9
10
  around_action :clear_storage
10
11
  rescue_from ActiveScaffold::RecordNotAllowed, ActiveScaffold::ActionNotAllowed, :with => :deny_access
11
12
  end
@@ -22,7 +23,7 @@ module ActiveScaffold::Actions
22
23
  end
23
24
 
24
25
  def render_field
25
- if request.get?
26
+ if request.get? || request.head?
26
27
  render_field_for_inplace_editing
27
28
  respond_to do |format|
28
29
  format.js { render :action => 'render_field_inplace', :layout => false }
@@ -61,14 +62,18 @@ module ActiveScaffold::Actions
61
62
  @source_id = params.delete(:source_id)
62
63
  @columns = @column.update_columns || []
63
64
  @scope = params.delete(:scope)
64
- action = :subform if @scope
65
- action ||= params[:id] ? :update : :create
66
- @main_columns = active_scaffold_config.send(action).columns
65
+ if @scope
66
+ @form_action = :subform
67
+ elsif active_scaffold_config.actions.include? params[:form_action]&.to_sym
68
+ @form_action = params.delete(:form_action).to_sym
69
+ end
70
+ @form_action ||= params[:id] ? :update : :create
71
+ @main_columns = active_scaffold_config.send(@form_action).columns
67
72
  @columns << @column.name if @column.options[:refresh_link] && @columns.exclude?(@column.name)
68
73
 
69
74
  @record =
70
75
  if @column.send_form_on_update_column
71
- updated_record_with_form(@main_columns, params[:record], @scope)
76
+ updated_record_with_form(@main_columns, params[:record] || params[:search], @scope)
72
77
  else
73
78
  updated_record_with_column(@column, params.delete(:value), @scope)
74
79
  end
@@ -100,7 +105,14 @@ module ActiveScaffold::Actions
100
105
  record = params[:id] ? copy_attributes(find_if_allowed(params[:id], :read)) : new_model
101
106
  apply_constraints_to_record(record) unless scope || params[:id]
102
107
  create_association_with_parent record, true if nested?
103
- update_column_from_params(record, column, value, true)
108
+ if @form_action == :field_search && value.is_a?(Array) && column.association&.singular?
109
+ # don't assign value if it's an array and column is singular association,
110
+ # e.g. value came from multi-select on search form
111
+ # use instance variable so it's available in the view and helpers
112
+ @value = value
113
+ else
114
+ update_column_from_params(record, column, value, true)
115
+ end
104
116
  record.id = params[:id]
105
117
  record
106
118
  end
@@ -165,6 +177,10 @@ module ActiveScaffold::Actions
165
177
  flash.clear if request.xhr?
166
178
  end
167
179
 
180
+ def dl_cookie
181
+ cookies[params[:_dl_cookie]] = {value: Time.now.to_i, expires: 1.day.since} if params[:_dl_cookie]
182
+ end
183
+
168
184
  def each_marked_record(&block)
169
185
  active_scaffold_config.model.as_marked.each(&block)
170
186
  end
@@ -248,7 +264,7 @@ module ActiveScaffold::Actions
248
264
  @conditions_from_params ||= begin
249
265
  conditions = [{}]
250
266
  params.except(:controller, :action, :page, :sort, :sort_direction, :format, :id).each do |key, value|
251
- distinct = true if key =~ /!$/
267
+ distinct = true if key.match?(/!$/)
252
268
  column = active_scaffold_config._columns_hash[key.to_s[0..(distinct ? -2 : -1)]]
253
269
  next unless column
254
270
  key = column.name.to_sym
@@ -321,7 +337,8 @@ module ActiveScaffold::Actions
321
337
 
322
338
  def check_input_device
323
339
  return unless session[:input_device_type].nil?
324
- if request.env['HTTP_USER_AGENT'] =~ /(iPhone|iPod|iPad)/i
340
+ return if request.env['HTTP_USER_AGENT'].nil?
341
+ if request.env['HTTP_USER_AGENT'].match?(/(iPhone|iPod|iPad)/i)
325
342
  session[:input_device_type] = 'TOUCH'
326
343
  session[:hover_supported] = false
327
344
  else
@@ -362,14 +379,14 @@ module ActiveScaffold::Actions
362
379
  # flash[:info] = 'Player fired'
363
380
  # end
364
381
  def process_action_link_action(render_action = :action_update, crud_type_or_security_options = nil)
365
- if request.get?
382
+ if request.get? || request.head?
366
383
  # someone has disabled javascript, we have to show confirmation form first
367
384
  @record = find_if_allowed(params[:id], :read) if params[:id]
368
385
  respond_to_action(:action_confirmation)
369
386
  else
370
387
  @action_link = active_scaffold_config.action_links[action_name]
371
388
  if params[:id]
372
- crud_type_or_security_options ||= {:crud_type => request.post? || request.put? ? :update : :delete, :action => action_name}
389
+ crud_type_or_security_options ||= {:crud_type => request.delete? ? :delete : :update, :action => action_name}
373
390
  get_row(crud_type_or_security_options)
374
391
  if @record.nil?
375
392
  self.successful = false
@@ -378,6 +395,9 @@ module ActiveScaffold::Actions
378
395
  yield @record
379
396
  end
380
397
  else
398
+ if @action_link && respond_to?(@action_link.security_method, true) && !send(@action_link.security_method)
399
+ raise ActiveScaffold::ActionNotAllowed
400
+ end
381
401
  yield
382
402
  end
383
403
  respond_to_action(render_action)
@@ -154,7 +154,6 @@ module ActiveScaffold::Actions
154
154
  filtered_columns = []
155
155
  text_search = active_scaffold_config.field_search.text_search
156
156
  columns = active_scaffold_config.field_search.columns
157
- count_includes = active_scaffold_config.list.user.count_includes
158
157
  search_params.each do |key, value|
159
158
  next unless columns.include? key
160
159
  column = active_scaffold_config.columns[key]
@@ -164,11 +163,7 @@ module ActiveScaffold::Actions
164
163
  active_scaffold_conditions << search_condition
165
164
  filtered_columns << column
166
165
  end
167
- if grouped_search? || active_scaffold_config.list.user.count_includes.present?
168
- active_scaffold_outer_joins.concat filtered_columns.map(&:search_joins).flatten.uniq.compact
169
- else
170
- set_outer_joins_for_search filtered_columns
171
- end
166
+ setup_joins_for_filtered_columns(filtered_columns)
172
167
  if filtered_columns.present? || grouped_search?
173
168
  @filtered = active_scaffold_config.field_search.human_conditions ? filtered_columns : true
174
169
  end
@@ -182,6 +177,14 @@ module ActiveScaffold::Actions
182
177
 
183
178
  private
184
179
 
180
+ def setup_joins_for_filtered_columns(filtered_columns)
181
+ if grouped_search? || active_scaffold_config.list.user.count_includes.present?
182
+ active_scaffold_outer_joins.concat filtered_columns.map(&:search_joins).flatten.uniq.compact
183
+ else
184
+ set_outer_joins_for_search filtered_columns
185
+ end
186
+ end
187
+
185
188
  def field_search_formats
186
189
  (default_formats + active_scaffold_config.formats + active_scaffold_config.field_search.formats).uniq
187
190
  end
@@ -8,7 +8,7 @@ module ActiveScaffold::Actions
8
8
  base.module_eval do
9
9
  before_action :set_nested
10
10
  before_action :configure_nested
11
- include ActiveScaffold::Actions::Nested::ChildMethods if active_scaffold_config.model.reflect_on_all_associations.any? { |a| a.macro == :has_and_belongs_to_many }
11
+ include ActiveScaffold::Actions::Nested::ChildMethods if active_scaffold_config.columns.map(&:association).compact.any?(&:habtm?)
12
12
  end
13
13
  base.before_action :include_habtm_actions
14
14
  base.helper_method :nested
@@ -120,9 +120,9 @@ module ActiveScaffold::Actions
120
120
 
121
121
  def create_association_with_parent?(check_match = false)
122
122
  # has_many is done by beginning_of_chain and rails if direct association, not in through associations
123
- return false if nested.has_many? && !nested.association.through?
123
+ return false unless nested.create_with_parent?
124
124
  return false if check_match && !nested.match_model?(active_scaffold_config.model)
125
- (nested.child_association || nested.create_through_singular?) && nested_parent_record
125
+ nested_parent_record.present?
126
126
  end
127
127
 
128
128
  def create_association_with_parent(record, check_match = false)
@@ -131,7 +131,7 @@ module ActiveScaffold::Actions
131
131
  record.send("#{nested.child_association.name}=", nested_parent_record)
132
132
  elsif nested.create_through_singular?
133
133
  through = nested_parent_record.send(nested.association.through_reflection.name) ||
134
- nested_parent_record.send("build_#{nested.association.through_reflection.name}")
134
+ nested_parent_record.send("build_#{nested.association.through_reflection.name}")
135
135
  if nested.source_reflection.reverse_association.collection?
136
136
  record.send(nested.source_reflection.reverse) << through
137
137
  else
@@ -167,7 +167,7 @@ module ActiveScaffold::Actions::Nested
167
167
  end
168
168
 
169
169
  def destroy_existing
170
- return redirect_to(params.merge(:action => :delete, :only_path => true)) if request.get?
170
+ return redirect_to(params.merge(:action => :delete, :only_path => true)) if request.get? || request.head?
171
171
  do_destroy_existing
172
172
  respond_to_action(:destroy_existing)
173
173
  end
@@ -247,8 +247,8 @@ module ActiveScaffold::Actions::Nested
247
247
  parent_record = nested_parent_record(:update)
248
248
  @record = active_scaffold_config.model.find(params[:associated_id])
249
249
  if parent_record && @record
250
- parent_record.send(nested.association.name) << @record
251
- parent_record.save
250
+ self.successful = false unless parent_record.send(nested.association.name) << @record
251
+ parent_record.save if successful?
252
252
  else
253
253
  false
254
254
  end
@@ -33,41 +33,10 @@ module ActiveScaffold
33
33
  module AttributeParams
34
34
  protected
35
35
 
36
- # workaround to update counters when polymorphic has_many changes on persisted record
37
- # TODO: remove when rails4 support is removed or counter cache for polymorphic has_many association works on rails4
38
- def hack_for_has_many_counter_cache(parent_record, column, value)
39
- association = parent_record.association(column.name)
40
- counter_attr = association.send(:cached_counter_attribute_name)
41
- difference = value.select(&:persisted?).size - parent_record.send(counter_attr)
42
-
43
- if parent_record.new_record?
44
- parent_record.send "#{column.name}=", value
45
- parent_record.send "#{counter_attr}_will_change!"
46
- else
47
- # don't decrement counter for deleted records, on destroy they will update counter
48
- difference += (parent_record.send(column.name) - value).size
49
- association.send :update_counter, difference unless difference.zero?
50
- end
51
-
52
- # update counters on old parents if belongs_to is changed
53
- value.select(&:persisted?).each do |record|
54
- key = record.send(column.association.foreign_key)
55
- parent_record.class.decrement_counter counter_attr, key if key && key != parent_record.id # rubocop:disable Rails/SkipsModelValidations
56
- end
57
- parent_record.send "#{column.name}=", value if parent_record.persisted?
58
- end
59
-
60
- # rails 4 needs this hack for polymorphic has_many
61
- # TODO: remove when hack_for_has_many_counter_cache is not needed
62
- def hack_for_has_many_counter_cache?(parent_record, column)
63
- column.association.counter_cache_hack? && parent_record.association(column.name).send(:has_cached_counter?)
64
- end
65
-
66
36
  # workaround for updating counters twice bug on rails4 (https://github.com/rails/rails/pull/14849)
67
- # rails 4 needs this hack for non-polymorphic belongs_to, when selecting record, not creating new one (value is Hash)
68
37
  # rails 5 needs this hack for belongs_to, when selecting record, not creating new one (value is Hash)
69
- # TODO: remove when pull request is merged and no version with bug is supported
70
- def counter_cache_hack?(association, value)
38
+ # TODO: remove when rails5 support is removed
39
+ def belongs_to_counter_cache_hack?(association, value)
71
40
  !params_hash?(value) && association.belongs_to? && association.counter_cache_hack?
72
41
  end
73
42
 
@@ -92,21 +61,19 @@ module ActiveScaffold
92
61
  multi_parameter_attrs = multi_parameter_attributes(attributes)
93
62
 
94
63
  columns.each_column(for: parent_record, crud_type: crud_type, flatten: true) do |column|
95
- begin
96
- # Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
97
- column.params.select { |p| attributes.key? p }.each { |p| parent_record.send("#{p}=", attributes[p]) }
64
+ # Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
65
+ column.params.select { |p| attributes.key? p }.each { |p| parent_record.send("#{p}=", attributes[p]) }
98
66
 
99
- if multi_parameter_attrs.key? column.name.to_s
100
- parent_record.send(:assign_multiparameter_attributes, multi_parameter_attrs[column.name.to_s])
101
- elsif attributes.key? column.name
102
- update_column_from_params(parent_record, column, attributes[column.name], avoid_changes)
103
- end
104
- rescue StandardError => e
105
- message = "on the ActiveScaffold column = :#{column.name} for #{parent_record.inspect} "\
106
- "(value from params #{attributes[column.name].inspect})"
107
- Rails.logger.error "#{e.class.name}: #{e.message} -- #{message}"
108
- raise
67
+ if multi_parameter_attrs.key? column.name.to_s
68
+ parent_record.send(:assign_multiparameter_attributes, multi_parameter_attrs[column.name.to_s])
69
+ elsif attributes.key? column.name
70
+ update_column_from_params(parent_record, column, attributes[column.name], avoid_changes)
109
71
  end
72
+ rescue StandardError => e
73
+ message = "on the ActiveScaffold column = :#{column.name} for #{parent_record.inspect} "\
74
+ "(value from params #{attributes[column.name].inspect})"
75
+ Rails.logger.error "#{e.class.name}: #{e.message} -- #{message}"
76
+ raise
110
77
  end
111
78
 
112
79
  parent_record
@@ -132,7 +99,7 @@ module ActiveScaffold
132
99
  end
133
100
 
134
101
  def update_column_association(parent_record, column, attribute, value)
135
- if counter_cache_hack?(column.association, attribute)
102
+ if belongs_to_counter_cache_hack?(column.association, attribute)
136
103
  parent_record.send "#{column.association.foreign_key}=", value&.id
137
104
  parent_record.association(column.name).target = value
138
105
  elsif column.association.collection? && column.association.through_singular?
@@ -140,8 +107,6 @@ module ActiveScaffold
140
107
  through_record = parent_record.send(through)
141
108
  through_record ||= parent_record.send "build_#{through}"
142
109
  through_record.send "#{column.association.source_reflection.name}=", value
143
- elsif hack_for_has_many_counter_cache?(parent_record, column)
144
- hack_for_has_many_counter_cache(parent_record, column, value)
145
110
  else
146
111
  parent_record.send "#{column.name}=", value
147
112
  end
@@ -184,7 +149,8 @@ module ActiveScaffold
184
149
 
185
150
  def association_value_from_param_simple_value(parent_record, column, value)
186
151
  if column.association.singular?
187
- column.association.klass(parent_record)&.find(value) if value.present?
152
+ # value may be Array if using update_columns in field_search with multi-select
153
+ column.association.klass(parent_record)&.find(value) if value.present? && !value.is_a?(Array)
188
154
  else # column.association.collection?
189
155
  column_plural_assocation_value_from_value(column, Array(value))
190
156
  end
@@ -327,13 +293,9 @@ module ActiveScaffold
327
293
  if ActiveScaffold::OrmChecks.mongoid? klass
328
294
  column.default_val
329
295
  elsif ActiveScaffold::OrmChecks.active_record? klass
330
- if Rails.version < '5.0'
331
- column.type_cast_from_database(column.default)
332
- else
333
- column_type = ActiveScaffold::OrmChecks.column_type(klass, column_name)
334
- cast_type = ActiveRecord::Type.lookup column_type
335
- cast_type ? cast_type.deserialize(column.default) : column.default
336
- end
296
+ column_type = ActiveScaffold::OrmChecks.column_type(klass, column_name)
297
+ cast_type = ActiveRecord::Type.lookup column_type
298
+ cast_type ? cast_type.deserialize(column.default) : column.default
337
299
  end
338
300
  end
339
301
  end
@@ -2,9 +2,6 @@ module ActiveScaffold
2
2
  module Bridges
3
3
  class ActiveStorage
4
4
  module ActiveStorageBridgeHelpers
5
- mattr_accessor :thumbnail_variant
6
- self.thumbnail_variant = {resize_to_limit: [nil, 30]}
7
-
8
5
  class << self
9
6
  # has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record, dependent: false
10
7
  def active_storage_has_one_fields(klass)
@@ -22,7 +22,7 @@ module ActiveScaffold
22
22
  private
23
23
 
24
24
  def link_for_attachment(attachment, column)
25
- variant = column.options[:thumb] || ActiveScaffold::Bridges::ActiveStorage::ActiveStorageBridgeHelpers.thumbnail_variant
25
+ variant = column.options[:thumb] || ActiveScaffold::Bridges::ActiveStorage.thumbnail_variant
26
26
  content =
27
27
  if variant && attachment.variable? && column.options[:thumb] != false
28
28
  image_tag(attachment.variant(variant))
@@ -1,4 +1,7 @@
1
1
  class ActiveScaffold::Bridges::ActiveStorage < ActiveScaffold::DataStructures::Bridge
2
+ cattr_accessor :thumbnail_variant
3
+ self.thumbnail_variant = {resize_to_limit: [nil, 30]}
4
+
2
5
  def self.install
3
6
  Dir[File.join(__dir__, 'active_storage', '*.rb')].each { |file| require file }
4
7
  ActiveScaffold::Config::Core.send :prepend, ActiveScaffold::Bridges::ActiveStorage::ActiveStorageBridge
@@ -8,9 +8,9 @@ module ActiveScaffold
8
8
 
9
9
  model.bitfields.each_value do |options|
10
10
  columns << options.keys
11
- options.each do |column, value|
11
+ options.each_key.with_index(1) do |column, i|
12
12
  columns[column].form_ui = :checkbox
13
- columns[column].weight = 1000 + value.to_s(2).size
13
+ columns[column].weight = 1000 + i
14
14
  end
15
15
  end
16
16
  end
@@ -1,6 +1,7 @@
1
1
  module ActiveScaffold::Bridges
2
2
  class DatePicker
3
3
  module Helper
4
+ UNSUPPORTED_FORMAT_OPTIONS = /%[cUWwxXZ]/
4
5
  DATE_FORMAT_CONVERSION = {
5
6
  /%a/ => 'D',
6
7
  /%A/ => 'DD',
@@ -19,7 +20,7 @@ module ActiveScaffold::Bridges
19
20
  /%p/ => 'tt',
20
21
  /%S/ => 'ss',
21
22
  /%z/ => 'z',
22
- /%[cUWwxXZ]/ => ''
23
+ UNSUPPORTED_FORMAT_OPTIONS => ''
23
24
  }.freeze
24
25
 
25
26
  def self.date_options_for_locales
@@ -83,9 +84,8 @@ module ActiveScaffold::Bridges
83
84
 
84
85
  def self.to_datepicker_format(rails_format)
85
86
  return nil if rails_format.nil?
86
- unsupported = DATE_FORMAT_CONVERSION.index ''
87
- if rails_format =~ unsupported
88
- options = unsupported.to_s.scan(/\[(.*)\]/).dig(0, 0)&.each_char&.map { |c| "%#{c}" }
87
+ if rails_format.match?(UNSUPPORTED_FORMAT_OPTIONS)
88
+ options = UNSUPPORTED_FORMAT_OPTIONS.to_s.scan(/\[(.*)\]/).dig(0, 0)&.each_char&.map { |c| "%#{c}" }
89
89
  Rails.logger.warn(
90
90
  "AS DatePicker::Helper: rails date format #{rails_format} includes options "\
91
91
  "which can't be converted to jquery datepicker format. "\
@@ -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)
@@ -51,7 +51,7 @@ 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
 
@@ -60,7 +60,7 @@ class ActiveScaffold::Bridges::RecordSelect
60
60
  :controller => active_scaffold_controller_for(record.class).controller_path
61
61
  ).merge(column.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
@@ -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
 
@@ -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?
@@ -271,14 +271,8 @@ module ActiveScaffold
271
271
 
272
272
  def self.active_record_column_type_cast(value, column)
273
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
+ cast_type = ActiveRecord::Type.lookup column.type
275
+ cast_type ? cast_type.cast(value) : value
282
276
  end
283
277
  end
284
278
  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