active_scaffold 3.5.5 → 3.6.0.pre

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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +18 -2
  3. data/README.md +17 -7
  4. data/app/assets/javascripts/jquery/active_scaffold.js +28 -2
  5. data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -2
  6. data/app/views/active_scaffold_overrides/_form.html.erb +1 -1
  7. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +3 -2
  8. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +6 -6
  9. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
  10. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
  11. data/app/views/active_scaffold_overrides/_list.html.erb +2 -1
  12. data/app/views/active_scaffold_overrides/_list_messages.html.erb +1 -0
  13. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -0
  14. data/app/views/active_scaffold_overrides/_render_field.js.erb +2 -1
  15. data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -1
  16. data/app/views/active_scaffold_overrides/_show_columns.html.erb +2 -2
  17. data/app/views/active_scaffold_overrides/_show_horizontal_record.html.erb +4 -4
  18. data/app/views/active_scaffold_overrides/_update_calculations.js.erb +1 -1
  19. data/app/views/active_scaffold_overrides/_update_column.js.erb +2 -2
  20. data/app/views/active_scaffold_overrides/action_confirmation.html.erb +2 -2
  21. data/app/views/active_scaffold_overrides/delete.html.erb +2 -2
  22. data/app/views/active_scaffold_overrides/on_action_update.js.erb +16 -6
  23. data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
  24. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  25. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  26. data/lib/active_scaffold.rb +11 -13
  27. data/lib/active_scaffold/actions/core.rb +25 -35
  28. data/lib/active_scaffold/actions/create.rb +1 -1
  29. data/lib/active_scaffold/actions/delete.rb +2 -2
  30. data/lib/active_scaffold/actions/field_search.rb +2 -2
  31. data/lib/active_scaffold/actions/list.rb +8 -7
  32. data/lib/active_scaffold/actions/nested.rb +9 -9
  33. data/lib/active_scaffold/actions/search.rb +1 -1
  34. data/lib/active_scaffold/actions/show.rb +1 -1
  35. data/lib/active_scaffold/actions/subform.rb +3 -1
  36. data/lib/active_scaffold/actions/update.rb +5 -4
  37. data/lib/active_scaffold/active_record_permissions.rb +2 -11
  38. data/lib/active_scaffold/attribute_params.rb +16 -23
  39. data/lib/active_scaffold/bridges.rb +8 -8
  40. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +1 -1
  41. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  42. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +3 -18
  43. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  44. data/lib/active_scaffold/bridges/chosen/helpers.rb +7 -6
  45. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  46. data/lib/active_scaffold/bridges/date_picker/helper.rb +3 -3
  47. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  48. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  49. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +8 -7
  50. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +2 -4
  51. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  52. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  53. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  54. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  55. data/lib/active_scaffold/bridges/record_select/helpers.rb +9 -9
  56. data/lib/active_scaffold/bridges/shared/date_bridge.rb +3 -3
  57. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +1 -1
  58. data/lib/active_scaffold/config/base.rb +89 -21
  59. data/lib/active_scaffold/config/core.rb +127 -18
  60. data/lib/active_scaffold/config/delete.rb +2 -0
  61. data/lib/active_scaffold/config/field_search.rb +7 -1
  62. data/lib/active_scaffold/config/form.rb +10 -1
  63. data/lib/active_scaffold/config/list.rb +27 -11
  64. data/lib/active_scaffold/config/mark.rb +3 -1
  65. data/lib/active_scaffold/config/nested.rb +16 -17
  66. data/lib/active_scaffold/config/search.rb +9 -0
  67. data/lib/active_scaffold/config/show.rb +4 -0
  68. data/lib/active_scaffold/config/update.rb +4 -0
  69. data/lib/active_scaffold/configurable.rb +11 -6
  70. data/lib/active_scaffold/constraints.rb +1 -1
  71. data/lib/active_scaffold/core.rb +46 -16
  72. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  73. data/lib/active_scaffold/data_structures/action_link.rb +20 -8
  74. data/lib/active_scaffold/data_structures/action_links.rb +6 -2
  75. data/lib/active_scaffold/data_structures/association/abstract.rb +9 -5
  76. data/lib/active_scaffold/data_structures/association/active_record.rb +1 -1
  77. data/lib/active_scaffold/data_structures/column.rb +51 -33
  78. data/lib/active_scaffold/data_structures/nested_info.rb +1 -1
  79. data/lib/active_scaffold/data_structures/set.rb +8 -0
  80. data/lib/active_scaffold/data_structures/sorting.rb +5 -2
  81. data/lib/active_scaffold/delayed_setup.rb +2 -1
  82. data/lib/active_scaffold/extensions/action_controller_rendering.rb +2 -1
  83. data/lib/active_scaffold/extensions/action_view_rendering.rb +1 -1
  84. data/lib/active_scaffold/extensions/cow_proxy.rb +43 -0
  85. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  86. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  87. data/lib/active_scaffold/extensions/routing_mapper.rb +4 -43
  88. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  89. data/lib/active_scaffold/finder.rb +26 -30
  90. data/lib/active_scaffold/helpers/action_link_helpers.rb +16 -16
  91. data/lib/active_scaffold/helpers/association_helpers.rb +5 -5
  92. data/lib/active_scaffold/helpers/controller_helpers.rb +11 -1
  93. data/lib/active_scaffold/helpers/form_column_helpers.rb +25 -24
  94. data/lib/active_scaffold/helpers/id_helpers.rb +2 -2
  95. data/lib/active_scaffold/helpers/list_column_helpers.rb +8 -6
  96. data/lib/active_scaffold/helpers/search_column_helpers.rb +4 -4
  97. data/lib/active_scaffold/helpers/view_helpers.rb +7 -13
  98. data/lib/active_scaffold/marked_model.rb +2 -2
  99. data/lib/active_scaffold/orm_checks.rb +1 -5
  100. data/lib/active_scaffold/paginator.rb +6 -4
  101. data/lib/active_scaffold/registry.rb +22 -0
  102. data/lib/active_scaffold/responds_to_parent.rb +2 -6
  103. data/lib/active_scaffold/tableless.rb +63 -59
  104. data/lib/active_scaffold/version.rb +2 -2
  105. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  106. data/lib/generators/active_scaffold/install_generator.rb +1 -1
  107. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  108. data/test/bridges/date_picker_test.rb +1 -2
  109. data/test/bridges/paperclip_test.rb +5 -5
  110. data/test/class_with_finder.rb +2 -2
  111. data/test/company.rb +2 -2
  112. data/test/config/create_test.rb +4 -2
  113. data/test/config/nested_test.rb +1 -1
  114. data/test/config/show_test.rb +1 -1
  115. data/test/config/update_test.rb +7 -6
  116. data/test/data_structures/action_links_test.rb +1 -1
  117. data/test/data_structures/sorting_test.rb +7 -0
  118. data/test/misc/active_record_permissions_test.rb +1 -9
  119. data/test/misc/attribute_params_test.rb +8 -8
  120. data/test/misc/calculation_test.rb +1 -1
  121. data/test/misc/constraints_test.rb +2 -2
  122. data/test/misc/convert_numbers_format_test.rb +3 -3
  123. data/test/misc/lang_test.rb +1 -1
  124. data/test/misc/parse_datetime_test.rb +3 -4
  125. data/test/misc/tableless_test.rb +6 -0
  126. data/test/mock_app/Rakefile +1 -1
  127. data/test/mock_app/config/application.rb +1 -1
  128. data/test/mock_app/config/boot.rb +1 -1
  129. data/test/mock_app/config/environment.rb +2 -2
  130. data/test/test_helper.rb +8 -1
  131. metadata +38 -13
@@ -26,5 +26,7 @@ module ActiveScaffold::Config
26
26
 
27
27
  # whether we should refresh list after destroy or not
28
28
  attr_accessor :refresh_list
29
+
30
+ undef_method :new_user_settings
29
31
  end
30
32
  end
@@ -1,6 +1,7 @@
1
1
  module ActiveScaffold::Config
2
2
  class FieldSearch < Base
3
3
  self.crud_type = :read
4
+ NO_COLUMNS = [].freeze
4
5
 
5
6
  def initialize(core_config)
6
7
  super
@@ -52,7 +53,8 @@ module ActiveScaffold::Config
52
53
  end
53
54
 
54
55
  def optional_columns
55
- @optional_columns ||= []
56
+ return @optional_columns || NO_COLUMNS if frozen?
57
+ @optional_columns ||= NO_COLUMNS.dup
56
58
  end
57
59
 
58
60
  # add array of columns as options for group by to get aggregated listings
@@ -68,5 +70,9 @@ module ActiveScaffold::Config
68
70
  # human conditions
69
71
  # instead of just filtered you may show the user a humanized search condition statment
70
72
  attr_accessor :human_conditions
73
+
74
+ UserSettings.class_eval do
75
+ user_attr :optional_columns, :group_options, :grouped_columns, :human_conditions
76
+ end
71
77
  end
72
78
  end
@@ -43,7 +43,7 @@ module ActiveScaffold::Config
43
43
 
44
44
  columns_accessor :columns do
45
45
  columns.exclude :created_on, :created_at, :updated_on, :updated_at, :as_marked
46
- columns.exclude(*@core.columns.collect { |c| c.name if c.association.try(:polymorphic?) }.compact)
46
+ columns.exclude(*@core.columns.collect { |c| c.name if c.association&.polymorphic? }.compact)
47
47
  end
48
48
 
49
49
  # whether the form should be multipart
@@ -51,5 +51,14 @@ module ActiveScaffold::Config
51
51
  def multipart?
52
52
  @multipart ? true : false
53
53
  end
54
+
55
+ UserSettings.class_eval do
56
+ user_attr :persistent, :refresh_list, :show_unauthorized_columns
57
+
58
+ attr_writer :multipart
59
+ def multipart?
60
+ defined?(@multipart) ? @multipart : @conf.multipart?
61
+ end
62
+ end
54
63
  end
55
64
  end
@@ -219,10 +219,15 @@ module ActiveScaffold::Config
219
219
  # order clause will be used for ETag when calculate_etag is disabled, so query for records can be avoided
220
220
  attr_accessor :calculate_etag
221
221
 
222
- class UserSettings < UserSettings
222
+ UserSettings.class_eval do # defined with columns_accessor
223
+ user_attr :page_links_inner_window, :page_links_outer_window, :refresh_with_header, :empty_field_text,
224
+ :association_join_text, :messages_above_header, :wrap_tag, :auto_select_columns, :calculate_etag,
225
+ :no_entries_message, :filtered_message, :show_search_reset, :always_show_create, :always_show_search,
226
+ :hide_nested_column
227
+
223
228
  def initialize(conf, storage, params)
224
229
  super(conf, storage, params, :list)
225
- @sorting = nil
230
+ @_sorting = nil
226
231
  end
227
232
 
228
233
  attr_writer :label
@@ -232,7 +237,7 @@ module ActiveScaffold::Config
232
237
  end
233
238
 
234
239
  def embedded_label
235
- @params[:embedded][:label] if @params[:embedded]
240
+ @params.dig :embedded, :label
236
241
  end
237
242
 
238
243
  def per_page
@@ -240,6 +245,10 @@ module ActiveScaffold::Config
240
245
  self['per_page'] || @conf.per_page
241
246
  end
242
247
 
248
+ def per_page=(value)
249
+ self['per_page'] = value
250
+ end
251
+
243
252
  def page
244
253
  self['page'] = @params['page'] || 1 if @params.key?('page') || @conf.auto_pagination
245
254
  self['page'] || 1
@@ -252,36 +261,43 @@ module ActiveScaffold::Config
252
261
  attr_reader :nested_default_sorting
253
262
 
254
263
  def nested_default_sorting=(options)
255
- @nested_default_sorting ||= @conf.sorting.clone
264
+ @nested_default_sorting ||= @conf.sorting.dup
256
265
  @nested_default_sorting.set_nested_sorting(options[:table_name], options[:default_sorting])
257
266
  end
258
267
 
259
268
  def default_sorting
260
- nested_default_sorting.nil? ? @conf.sorting.clone : nested_default_sorting
269
+ nested_default_sorting.nil? || @sorting.present? ? @conf.sorting.dup : nested_default_sorting
261
270
  end
262
271
 
272
+ # TODO: programatically set sorting, for per-request configuration, priority @params, then @sort
273
+
263
274
  def user_sorting?
264
275
  @params['sort'] && @params['sort_direction'] != 'reset'
265
276
  end
266
277
 
278
+ # change list sorting for this request, unless sorting is defined
279
+ # {column => direction, column => direction}
280
+ attr_writer :sorting
281
+
267
282
  def sorting
268
- if @sorting.nil?
283
+ if @_sorting.nil?
269
284
  # we want to store as little as possible in the session, but we want to return a Sorting data structure. so we recreate it each page load based on session data.
270
285
  self['sort'] = [@params['sort'], @params['sort_direction']] if @params['sort'] && @params['sort_direction']
271
286
  self['sort'] = nil if @params['sort_direction'] == 'reset'
272
287
 
273
288
  if self['sort'] && @conf.core.columns[self['sort'][0]]
274
- sorting = @conf.sorting.clone
289
+ sorting = @conf.sorting.dup
275
290
  sorting.set(*self['sort'])
276
- @sorting = sorting
291
+ @_sorting = sorting
277
292
  else
278
- @sorting = default_sorting
293
+ @_sorting = default_sorting
294
+ @_sorting.set(@sorting) if @sorting
279
295
  if @conf.columns.constraint_columns.present?
280
- @sorting.constraint_columns = @conf.columns.constraint_columns
296
+ @_sorting.constraint_columns = @conf.columns.constraint_columns
281
297
  end
282
298
  end
283
299
  end
284
- @sorting
300
+ @_sorting
285
301
  end
286
302
 
287
303
  def count_includes
@@ -24,7 +24,9 @@ module ActiveScaffold::Config
24
24
  @core.columns[:as_marked].label = 'M'
25
25
  @core.columns[:as_marked].list_ui = :marked
26
26
  @core.columns[:as_marked].sort = false
27
- @core.list.columns = [:as_marked] + @core.list.columns.names_without_auth_check unless @core.list.columns.include? :as_marked
27
+ @core.list.columns = [:as_marked] + @core.list.columns.to_a unless @core.list.columns.include? :as_marked
28
28
  end
29
+
30
+ undef_method :new_user_settings
29
31
  end
30
32
  end
@@ -25,23 +25,20 @@ module ActiveScaffold::Config
25
25
  # Add a nested ActionLink
26
26
  def add_link(attribute, options = {})
27
27
  column = @core.columns[attribute.to_sym]
28
- if column && column.association
29
- label =
30
- if column.association.polymorphic?
31
- column.label
32
- else
33
- column.association.klass.model_name.human(:count => column.association.singular? ? 1 : 2, :default => column.association.klass.name.pluralize)
34
- end
35
- options.reverse_merge! :security_method => :nested_authorized?, :label => label
36
- action_group = options.delete(:action_group) || self.action_group
37
- action_link = @core.link_for_association(column, options)
38
- @core.action_links.add_to_group(action_link, action_group) unless action_link.nil?
39
- action_link
40
- elsif column.nil?
41
- raise ArgumentError, "unknown column #{attribute}"
42
- elsif column.association.nil?
43
- raise ArgumentError, "column #{attribute} is not an association"
44
- end
28
+ raise ArgumentError, "unknown column #{attribute}" if column.nil?
29
+ raise ArgumentError, "column #{attribute} is not an association" if column.association.nil?
30
+
31
+ label =
32
+ if column.association.polymorphic?
33
+ column.label
34
+ else
35
+ column.association.klass.model_name.human(:count => column.association.singular? ? 1 : 2, :default => column.association.klass.name.pluralize)
36
+ end
37
+ options.reverse_merge! :security_method => :nested_authorized?, :label => label
38
+ action_group = options.delete(:action_group) || self.action_group
39
+ action_link = @core.link_for_association(column, options)
40
+ @core.action_links.add_to_group(action_link, action_group) unless action_link.nil?
41
+ action_link
45
42
  end
46
43
 
47
44
  def add_scoped_link(named_scope, options = {})
@@ -51,5 +48,7 @@ module ActiveScaffold::Config
51
48
 
52
49
  # the label for this Nested action. used for the header.
53
50
  attr_writer :label
51
+
52
+ undef_method :new_user_settings
54
53
  end
55
54
  end
@@ -64,5 +64,14 @@ module ActiveScaffold::Config
64
64
  def live?
65
65
  @live
66
66
  end
67
+
68
+ UserSettings.class_eval do
69
+ attr_writer :live
70
+ def live?
71
+ defined?(@live) ? @live : @conf.live?
72
+ end
73
+
74
+ user_attr :text_search, :split_terms
75
+ end
67
76
  end
68
77
  end
@@ -25,5 +25,9 @@ module ActiveScaffold::Config
25
25
  attr_writer :label
26
26
 
27
27
  columns_accessor :columns
28
+
29
+ UserSettings.class_eval do
30
+ user_attr :inline_links
31
+ end
28
32
  end
29
33
  end
@@ -32,5 +32,9 @@ module ActiveScaffold::Config
32
32
  def hide_nested_column
33
33
  @hide_nested_column.nil? ? true : @hide_nested_column
34
34
  end
35
+
36
+ UserSettings.class_eval do
37
+ user_attr :nested_links, :hide_nested_column
38
+ end
35
39
  end
36
40
  end
@@ -13,14 +13,19 @@ module ActiveScaffold
13
13
  ret
14
14
  end
15
15
 
16
- # this method will surely need tweaking. for example, i'm not sure if it should call super before or after it tries to eval with the binding.
17
16
  def method_missing(name, *args)
18
- super
19
- rescue NoMethodError, NameError
20
- if @configuration_binding.nil?
21
- raise
22
- else
17
+ if @configuration_binding&.respond_to?(name, true)
23
18
  @configuration_binding.send(name, *args)
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ def respond_to_missing?(name, include_all = false)
25
+ if @configuration_binding
26
+ @configuration_binding.respond_to?(name, include_all)
27
+ else
28
+ super
24
29
  end
25
30
  end
26
31
  end
@@ -143,7 +143,7 @@ module ActiveScaffold
143
143
  config = record.is_a?(active_scaffold_config.model) ? active_scaffold_config : active_scaffold_config_for(record.class)
144
144
  constraints.each do |k, v|
145
145
  column = config.columns[k]
146
- if column && column.association
146
+ if column&.association
147
147
  if column.association.collection?
148
148
  record.send(k.to_s).send(:<<, column.association.klass.find(v))
149
149
  elsif column.association.polymorphic?
@@ -4,12 +4,43 @@ module ActiveScaffold
4
4
  base.extend(ClassMethods)
5
5
  end
6
6
 
7
+ def setup_user_settings
8
+ config = self.class.active_scaffold_config
9
+ config.new_user_settings(user_settings_storage, params)
10
+ unless ActiveScaffold.threadsafe
11
+ config.actions.each do |action_name|
12
+ conf_instance = config.send(action_name) rescue next # rubocop:disable Style/RescueModifier
13
+ config.user.action_user_settings(conf_instance)
14
+ end
15
+ end
16
+ end
17
+
7
18
  def active_scaffold_config
8
- self.class.active_scaffold_config
19
+ setup_user_settings unless self.class.active_scaffold_config.user
20
+ if ActiveScaffold.threadsafe
21
+ self.class.active_scaffold_config.user
22
+ else
23
+ self.class.active_scaffold_config
24
+ end
25
+ end
26
+
27
+ def active_scaffold_session_storage_key(id = nil)
28
+ id ||= params[:eid] || "#{params[:controller]}#{"_#{nested_parent_id}" if nested?}"
29
+ "as:#{id}"
9
30
  end
10
31
 
11
- def active_scaffold_config_for(klass)
12
- self.class.active_scaffold_config_for(klass)
32
+ def active_scaffold_session_storage(id = nil)
33
+ session_index = active_scaffold_session_storage_key(id)
34
+ session[session_index] ||= {}
35
+ session[session_index]
36
+ end
37
+
38
+ def user_settings_storage
39
+ if self.class.active_scaffold_config.store_user_settings
40
+ active_scaffold_session_storage
41
+ else
42
+ {}
43
+ end
13
44
  end
14
45
 
15
46
  module ClassMethods
@@ -30,7 +61,6 @@ module ActiveScaffold
30
61
  active_scaffold_config.sti_children = nil # reset sti_children if set in parent block
31
62
  active_scaffold_config.configure(&block) if block_given?
32
63
  active_scaffold_config._configure_sti unless active_scaffold_config.sti_children.nil?
33
- active_scaffold_config._load_action_columns
34
64
 
35
65
  # defines the attribute read methods on the model, so record.send() doesn't find protected/private methods instead
36
66
  # define_attribute_methods is safe to call multiple times since rails 4.0.4
@@ -46,6 +76,7 @@ module ActiveScaffold
46
76
  active_scaffold_config.actions.each do |mod|
47
77
  include "ActiveScaffold::Actions::#{mod.to_s.camelize}".constantize
48
78
  mod_conf = active_scaffold_config.send(mod)
79
+ active_scaffold_config._setup_action(mod) if ActiveScaffold.threadsafe
49
80
  next unless mod_conf.respond_to?(:link) && (link = mod_conf.link)
50
81
 
51
82
  # sneak the action links from the actions into the main set
@@ -59,10 +90,14 @@ module ActiveScaffold
59
90
  end
60
91
  end
61
92
  _add_sti_create_links if active_scaffold_config.add_sti_create_links?
93
+ if ActiveScaffold.threadsafe
94
+ active_scaffold_config._cache_lazy_values
95
+ active_scaffold_config.deep_freeze!
96
+ end
62
97
  end
63
98
 
64
99
  module Prefixes
65
- define_method Rails.version < '4.2' ? 'parent_prefixes' : 'local_prefixes' do
100
+ define_method 'local_prefixes' do
66
101
  @local_prefixes ||= begin
67
102
  prefixes = super()
68
103
  unless superclass.uses_active_scaffold? || prefixes.include?('active_scaffold_overrides')
@@ -167,17 +202,14 @@ module ActiveScaffold
167
202
  end
168
203
 
169
204
  def active_scaffold_config_for(klass)
170
- controller = active_scaffold_controller_for(klass)
205
+ active_scaffold_controller_for(klass).active_scaffold_config
171
206
  rescue ActiveScaffold::ControllerNotFound
172
- config = ActiveScaffold::Config::Core.new(klass)
173
- config._load_action_columns
174
- config
175
- else
176
- controller.active_scaffold_config
207
+ ActiveScaffold::Config::Core.new(klass)
177
208
  end
178
209
 
179
210
  def active_scaffold_controller_for(klass)
180
211
  return self if uses_active_scaffold? && klass == active_scaffold_config.model
212
+ # noinspection RubyArgCount
181
213
  ActiveScaffold::Core.active_scaffold_controller_for(klass, to_s.deconstantize + '::')
182
214
  end
183
215
 
@@ -216,9 +248,9 @@ module ActiveScaffold
216
248
  end
217
249
 
218
250
  def self.column_type_cast(value, column)
219
- if defined?(ActiveRecord) && ActiveRecord::ConnectionAdapters::Column === column
251
+ if defined?(ActiveRecord) && column.is_a?(ActiveRecord::ConnectionAdapters::Column)
220
252
  active_record_column_type_cast(value, column)
221
- elsif defined?(Mongoid) && Mongoid::Fields::Standard === column
253
+ elsif defined?(Mongoid) && column.is_a?(Mongoid::Fields::Standard)
222
254
  mongoid_column_type_cast(value, column)
223
255
  else
224
256
  value
@@ -230,9 +262,7 @@ module ActiveScaffold
230
262
  end
231
263
 
232
264
  def self.active_record_column_type_cast(value, column)
233
- if Rails.version < '4.2'
234
- column.type_cast value
235
- elsif Rails.version < '5.0'
265
+ if Rails.version < '5.0'
236
266
  column.type_cast_from_user value
237
267
  elsif column.type.respond_to? :cast # jruby-jdbc and rails 5
238
268
  column.type.cast value
@@ -52,82 +52,77 @@ module ActiveScaffold::DataStructures
52
52
  false
53
53
  end
54
54
 
55
- def names
56
- if @columns
57
- collect_visible(:flatten => true, &:name)
58
- else
59
- names_without_auth_check
60
- end
55
+ def to_a
56
+ Array(@set)
61
57
  end
62
58
 
63
- def names_without_auth_check
64
- Array(@set)
59
+ def skip_column?(column_name, options)
60
+ # skip if this matches a constrained column
61
+ return true if constraint_columns.include?(column_name.to_sym)
62
+ # skip this field if it's not authorized
63
+ unless options[:for].authorized_for?(action: options[:action], crud_type: options[:crud_type] || action&.crud_type || :read, column: column_name)
64
+ unauthorized_columns << column_name.to_sym
65
+ return true
66
+ end
67
+ false
65
68
  end
66
69
 
67
- # Redefine the each method to yield actual Column objects.
68
- # It will skip constrained and unauthorized columns.
69
- #
70
- # Options:
71
- # * :flatten - whether to recursively iterate on nested sets. default is false.
72
- # * :for - the record (or class) being iterated over. used for column-level security. default is the class.
73
- def each(options = {}, &proc)
74
- options[:for] ||= @columns.active_record_class unless @columns.nil?
70
+ def each_column(options = {}, &proc)
71
+ columns = action.core.columns
75
72
  self.unauthorized_columns = []
76
- @set.each do |item|
77
- unless item.is_a?(ActiveScaffold::DataStructures::ActionColumns) || @columns.nil?
78
- item = (@columns[item] || ActiveScaffold::DataStructures::Column.new(item.to_sym, @columns.active_record_class))
79
- next if skip_column?(item, options)
80
- end
73
+ options[:for] ||= columns.active_record_class
74
+
75
+ each do |item|
81
76
  if item.is_a? ActiveScaffold::DataStructures::ActionColumns
82
77
  if options[:flatten]
83
- item.each(options, &proc)
78
+ item.each_column(options, &proc)
84
79
  elsif !options[:skip_groups]
85
80
  yield item
86
81
  end
87
82
  else
88
- yield item
83
+ next if skip_column?(item, options)
84
+ yield columns[item] || ActiveScaffold::DataStructures::Column.new(item.to_sym, columns.active_record_class)
89
85
  end
90
86
  end
91
87
  end
92
88
 
93
- def collect_visible(options = {}, &proc)
89
+ def visible_columns(options = {})
94
90
  columns = []
95
- options[:for] ||= @columns.active_record_class
96
- self.unauthorized_columns = []
97
- @set.each do |item|
98
- unless item.is_a?(ActiveScaffold::DataStructures::ActionColumns) || @columns.nil?
99
- item = (@columns[item] || ActiveScaffold::DataStructures::Column.new(item.to_sym, @columns.active_record_class))
100
- next if skip_column?(item, options)
101
- end
102
- if item.is_a?(ActiveScaffold::DataStructures::ActionColumns) && options.key?(:flatten) && options[:flatten]
103
- columns += item.collect_visible(options, &proc)
104
- else
105
- columns << (block_given? ? yield(item) : item)
106
- end
91
+ each_column(options) do |column|
92
+ columns << column
107
93
  end
108
94
  columns
109
95
  end
110
96
 
111
- def skip_column?(column, options)
112
- # skip if this matches a constrained column
113
- return true if constraint_columns.include?(column.name.to_sym)
114
- # skip this field if it's not authorized
115
- unless options[:for].authorized_for?(:action => options[:action], :crud_type => options[:crud_type] || action.try(:crud_type) || :read, :column => column.name)
116
- unauthorized_columns << column.name.to_sym
117
- return true
118
- end
119
- false
97
+ def visible_columns_names(options = {})
98
+ visible_columns(options.reverse_merge(flatten: true)).map(&:name)
120
99
  end
121
100
 
122
- # registers a set of column objects (recursively, for all nested ActionColumns)
123
- def set_columns(columns)
124
- @columns = columns
125
- # iterate over @set instead of self to avoid dealing with security queries
126
- @set.each do |item|
127
- item.set_columns(columns) if item.respond_to? :set_columns
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)
128
107
  end
129
108
  end
130
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
+
131
126
  def action_name
132
127
  @action.class.name.demodulize.underscore
133
128
  end
@@ -137,23 +132,19 @@ module ActiveScaffold::DataStructures
137
132
  end
138
133
 
139
134
  def constraint_columns=(columns)
140
- Thread.current[:constraint_columns] ||= {}
141
- Thread.current[:constraint_columns][columns_key] = columns
135
+ ActiveScaffold::Registry.constraint_columns[columns_key] = columns
142
136
  end
143
137
 
144
138
  def constraint_columns
145
- constraints = Thread.current[:constraint_columns]
146
- (constraints[columns_key] if constraints) || []
139
+ ActiveScaffold::Registry.constraint_columns[columns_key]
147
140
  end
148
141
 
149
142
  def unauthorized_columns=(columns)
150
- Thread.current[:unauthorized_columns] ||= {}
151
- Thread.current[:unauthorized_columns][columns_key] = columns
143
+ ActiveScaffold::Registry.unauthorized_columns[columns_key] = columns
152
144
  end
153
145
 
154
146
  def unauthorized_columns
155
- Thread.current[:unauthorized_columns] ||= {}
156
- Thread.current[:unauthorized_columns][columns_key] ||= []
147
+ ActiveScaffold::Registry.unauthorized_columns[columns_key]
157
148
  end
158
149
 
159
150
  def length