active_scaffold 3.6.20 → 3.7.0

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