active_scaffold 3.5.4 → 3.6.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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +72 -0
  3. data/README.md +20 -8
  4. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  5. data/app/assets/javascripts/jquery/active_scaffold.js +98 -7
  6. data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
  7. data/app/assets/stylesheets/active_scaffold_layout.css +52 -29
  8. data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -2
  9. data/app/views/active_scaffold_overrides/_form.html.erb +1 -1
  10. data/app/views/active_scaffold_overrides/_form_association.html.erb +2 -1
  11. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +3 -2
  12. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +9 -7
  13. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +4 -4
  14. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
  15. data/app/views/active_scaffold_overrides/_list.html.erb +2 -1
  16. data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
  17. data/app/views/active_scaffold_overrides/_list_messages.html.erb +1 -0
  18. data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
  19. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
  20. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -0
  21. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
  22. data/app/views/active_scaffold_overrides/_render_field.js.erb +2 -1
  23. data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -1
  24. data/app/views/active_scaffold_overrides/_show_columns.html.erb +2 -2
  25. data/app/views/active_scaffold_overrides/_show_horizontal_record.html.erb +4 -4
  26. data/app/views/active_scaffold_overrides/_update_calculations.js.erb +1 -1
  27. data/app/views/active_scaffold_overrides/_update_column.js.erb +2 -2
  28. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +2 -2
  29. data/app/views/active_scaffold_overrides/action_confirmation.html.erb +2 -2
  30. data/app/views/active_scaffold_overrides/delete.html.erb +2 -2
  31. data/app/views/active_scaffold_overrides/on_action_update.js.erb +16 -6
  32. data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
  33. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  34. data/app/views/active_scaffold_overrides/update_column.js.erb +2 -2
  35. data/config/locales/de.yml +2 -1
  36. data/config/locales/en.yml +1 -0
  37. data/config/locales/es.yml +1 -0
  38. data/config/locales/fr.yml +2 -1
  39. data/config/locales/hu.yml +1 -0
  40. data/config/locales/ja.yml +1 -0
  41. data/config/locales/ru.yml +1 -0
  42. data/lib/active_scaffold.rb +19 -16
  43. data/lib/active_scaffold/actions/common_search.rb +11 -8
  44. data/lib/active_scaffold/actions/core.rb +91 -70
  45. data/lib/active_scaffold/actions/create.rb +28 -28
  46. data/lib/active_scaffold/actions/delete.rb +3 -3
  47. data/lib/active_scaffold/actions/field_search.rb +53 -43
  48. data/lib/active_scaffold/actions/list.rb +111 -27
  49. data/lib/active_scaffold/actions/nested.rb +65 -48
  50. data/lib/active_scaffold/actions/search.rb +1 -1
  51. data/lib/active_scaffold/actions/show.rb +4 -4
  52. data/lib/active_scaffold/actions/subform.rb +23 -22
  53. data/lib/active_scaffold/actions/update.rb +96 -77
  54. data/lib/active_scaffold/active_record_permissions.rb +2 -11
  55. data/lib/active_scaffold/attribute_params.rb +102 -94
  56. data/lib/active_scaffold/bridges.rb +8 -8
  57. data/lib/active_scaffold/bridges/active_storage.rb +6 -0
  58. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +34 -0
  59. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
  60. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
  61. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
  62. data/lib/active_scaffold/bridges/bitfields.rb +2 -1
  63. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  64. data/lib/active_scaffold/bridges/bitfields/list_ui.rb +19 -0
  65. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  66. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -12
  67. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  68. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  69. data/lib/active_scaffold/bridges/chosen/helpers.rb +7 -6
  70. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  71. data/lib/active_scaffold/bridges/date_picker/helper.rb +49 -44
  72. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  73. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  74. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  75. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  76. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +10 -7
  77. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  78. data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
  79. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  80. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  81. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  82. data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -17
  83. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -19
  84. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  85. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +21 -4
  86. data/lib/active_scaffold/config/base.rb +133 -41
  87. data/lib/active_scaffold/config/core.rb +146 -18
  88. data/lib/active_scaffold/config/delete.rb +14 -1
  89. data/lib/active_scaffold/config/field_search.rb +7 -1
  90. data/lib/active_scaffold/config/form.rb +10 -1
  91. data/lib/active_scaffold/config/list.rb +39 -13
  92. data/lib/active_scaffold/config/mark.rb +4 -2
  93. data/lib/active_scaffold/config/nested.rb +16 -17
  94. data/lib/active_scaffold/config/search.rb +9 -0
  95. data/lib/active_scaffold/config/show.rb +4 -0
  96. data/lib/active_scaffold/config/update.rb +4 -0
  97. data/lib/active_scaffold/configurable.rb +14 -7
  98. data/lib/active_scaffold/constraints.rb +22 -20
  99. data/lib/active_scaffold/core.rb +67 -28
  100. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  101. data/lib/active_scaffold/data_structures/action_link.rb +50 -20
  102. data/lib/active_scaffold/data_structures/action_links.rb +15 -13
  103. data/lib/active_scaffold/data_structures/association/abstract.rb +38 -15
  104. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  105. data/lib/active_scaffold/data_structures/association/active_record.rb +6 -2
  106. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  107. data/lib/active_scaffold/data_structures/column.rb +75 -66
  108. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  109. data/lib/active_scaffold/data_structures/nested_info.rb +33 -19
  110. data/lib/active_scaffold/data_structures/set.rb +8 -0
  111. data/lib/active_scaffold/data_structures/sorting.rb +10 -2
  112. data/lib/active_scaffold/delayed_setup.rb +16 -5
  113. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -2
  114. data/lib/active_scaffold/extensions/action_view_rendering.rb +93 -32
  115. data/lib/active_scaffold/extensions/cow_proxy.rb +95 -0
  116. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  117. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  118. data/lib/active_scaffold/extensions/localize.rb +3 -1
  119. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -45
  120. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  121. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  122. data/lib/active_scaffold/finder.rb +110 -77
  123. data/lib/active_scaffold/helpers/action_link_helpers.rb +62 -36
  124. data/lib/active_scaffold/helpers/association_helpers.rb +18 -16
  125. data/lib/active_scaffold/helpers/controller_helpers.rb +34 -10
  126. data/lib/active_scaffold/helpers/form_column_helpers.rb +196 -124
  127. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  128. data/lib/active_scaffold/helpers/id_helpers.rb +6 -2
  129. data/lib/active_scaffold/helpers/list_column_helpers.rb +90 -57
  130. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  131. data/lib/active_scaffold/helpers/search_column_helpers.rb +29 -34
  132. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  133. data/lib/active_scaffold/helpers/view_helpers.rb +39 -36
  134. data/lib/active_scaffold/marked_model.rb +2 -2
  135. data/lib/active_scaffold/orm_checks.rb +3 -7
  136. data/lib/active_scaffold/paginator.rb +7 -7
  137. data/lib/active_scaffold/registry.rb +33 -0
  138. data/lib/active_scaffold/responds_to_parent.rb +8 -11
  139. data/lib/active_scaffold/tableless.rb +82 -66
  140. data/lib/active_scaffold/version.rb +2 -2
  141. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  142. data/lib/generators/active_scaffold/install_generator.rb +52 -4
  143. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  144. data/shoulda_macros/macros.rb +3 -1
  145. data/test/bridges/date_picker_test.rb +1 -2
  146. data/test/bridges/paperclip_test.rb +6 -6
  147. data/test/class_with_finder.rb +2 -2
  148. data/test/company.rb +4 -4
  149. data/test/config/create_test.rb +4 -2
  150. data/test/config/nested_test.rb +1 -1
  151. data/test/config/show_test.rb +1 -1
  152. data/test/config/update_test.rb +7 -6
  153. data/test/data_structures/action_columns_test.rb +2 -2
  154. data/test/data_structures/action_links_test.rb +1 -1
  155. data/test/data_structures/column_test.rb +3 -6
  156. data/test/data_structures/columns_test.rb +2 -2
  157. data/test/data_structures/sorting_test.rb +7 -0
  158. data/test/extensions/action_view_rendering_test.rb +20 -0
  159. data/test/extensions/active_record_test.rb +4 -4
  160. data/test/extensions/routing_mapper_test.rb +2 -2
  161. data/test/helpers/list_column_helpers_test.rb +3 -1
  162. data/test/misc/active_record_permissions_test.rb +3 -11
  163. data/test/misc/attribute_params_test.rb +12 -8
  164. data/test/misc/calculation_test.rb +1 -1
  165. data/test/misc/configurable_test.rb +10 -10
  166. data/test/misc/constraints_test.rb +2 -2
  167. data/test/misc/convert_numbers_format_test.rb +7 -3
  168. data/test/misc/lang_test.rb +1 -1
  169. data/test/misc/parse_datetime_test.rb +3 -4
  170. data/test/misc/tableless_test.rb +14 -0
  171. data/test/mock_app/Rakefile +1 -1
  172. data/test/mock_app/app/assets/config/manifest.js +0 -0
  173. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  174. data/test/mock_app/app/controllers/people_controller.rb +5 -1
  175. data/test/mock_app/app/controllers/roles_controller.rb +4 -0
  176. data/test/mock_app/app/views/active_scaffold_overrides/_form.html.erb +2 -0
  177. data/test/mock_app/app/views/active_scaffold_overrides/list.html.erb +2 -0
  178. data/test/mock_app/app/views/people/_first_name_form_column.html.erb +2 -0
  179. data/test/mock_app/app/views/people/_form.html.erb +2 -0
  180. data/test/mock_app/app/views/people/list.html.erb +2 -0
  181. data/test/mock_app/config/application.rb +2 -1
  182. data/test/mock_app/config/boot.rb +1 -1
  183. data/test/mock_app/config/environment.rb +2 -2
  184. data/test/mock_app/config/routes.rb +4 -1
  185. data/test/mock_app/db/schema.rb +2 -0
  186. data/test/performance/list_cars_performance_test.rb +34 -0
  187. data/test/performance/list_people_performance_test.rb +31 -0
  188. data/test/performance_test_help.rb +3 -0
  189. data/test/test_helper.rb +12 -4
  190. metadata +69 -18
  191. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  192. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -7
@@ -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
@@ -1,5 +1,7 @@
1
1
  module ActiveScaffold
2
- # Exposes a +configure+ method that accepts a block and runs all contents of the block in two contexts, as opposed to the normal one. First, everything gets evaluated as part of the object including Configurable. Then, as a failover, missing methods and variables are evaluated in the original binding of the block.
2
+ # Exposes a +configure+ method that accepts a block and runs all contents of the block in two contexts,
3
+ # as opposed to the normal one. First, everything gets evaluated as part of the object including Configurable.
4
+ # Then, as a failover, missing methods and variables are evaluated in the original binding of the block.
3
5
  #
4
6
  # Note that this only works with "barewords". Constants, instance variables, and class variables are not currently supported in both contexts.
5
7
  #
@@ -13,14 +15,19 @@ module ActiveScaffold
13
15
  ret
14
16
  end
15
17
 
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
18
  def method_missing(name, *args)
18
- super
19
- rescue NoMethodError, NameError
20
- if @configuration_binding.nil?
21
- raise
22
- else
19
+ if @configuration_binding&.respond_to?(name, true)
23
20
  @configuration_binding.send(name, *args)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ def respond_to_missing?(name, include_all = false)
27
+ if defined? @configuration_binding
28
+ @configuration_binding&.respond_to?(name, include_all)
29
+ else
30
+ super
24
31
  end
25
32
  end
26
33
  end
@@ -61,15 +61,7 @@ module ActiveScaffold
61
61
 
62
62
  # association column constraint
63
63
  elsif column.association
64
- if column.association.habtm?
65
- active_scaffold_habtm_joins.concat column.includes
66
- elsif !column.association.polymorphic?
67
- if column.association.belongs_to?
68
- active_scaffold_preload.concat column.includes
69
- else
70
- active_scaffold_references.concat column.includes
71
- end
72
- end
64
+ join_from_association_constraint(column)
73
65
  hash_conditions.deep_merge!(condition_from_association_constraint(column.association, v))
74
66
 
75
67
  # regular column constraints
@@ -78,7 +70,7 @@ module ActiveScaffold
78
70
  conditions << [column.search_sql.collect { |search_sql| "#{search_sql} = ?" }.join(' OR '), *([v] * column.search_sql.size)]
79
71
  end
80
72
  # unknown-to-activescaffold-but-real-database-column constraint
81
- elsif active_scaffold_config.model.columns_hash[k.to_s] && params[column.name] != v
73
+ elsif active_scaffold_config._columns_hash[k.to_s] && params[column.name] != v
82
74
  hash_conditions.deep_merge!(k => v)
83
75
  else
84
76
  raise ActiveScaffold::MalformedConstraint, constraint_error(active_scaffold_config.model, k), caller
@@ -87,6 +79,18 @@ module ActiveScaffold
87
79
  conditions.reject(&:blank?)
88
80
  end
89
81
 
82
+ def join_from_association_constraint(column)
83
+ if column.association.habtm?
84
+ active_scaffold_habtm_joins.concat column.includes
85
+ elsif !column.association.polymorphic?
86
+ if column.association.belongs_to?
87
+ active_scaffold_preload.concat column.includes
88
+ else
89
+ active_scaffold_references.concat column.includes
90
+ end
91
+ end
92
+ end
93
+
90
94
  # We do NOT want to use .search_sql. If anything, search_sql will refer
91
95
  # to a human-searchable value on the associated record.
92
96
  def condition_from_association_constraint(association, value)
@@ -96,17 +100,15 @@ module ActiveScaffold
96
100
  #
97
101
  # please see the relevant tests for concrete examples.
98
102
 
99
- field = if association.belongs_to?
100
- association.foreign_key
101
- else
102
- association.klass.primary_key
103
+ field =
104
+ if association.belongs_to?
105
+ association.foreign_key
106
+ else
107
+ association.klass.primary_key
103
108
  end
104
109
 
105
110
  table = association.belongs_to? ? active_scaffold_config.model.table_name : association.table_name
106
-
107
- if association.primary_key
108
- value = association.klass.find(value).send(association.primary_key)
109
- end
111
+ value = association.klass.find(value).send(association.primary_key) if association.primary_key
110
112
 
111
113
  if association.polymorphic?
112
114
  unless value.is_a?(Array) && value.size == 2
@@ -143,7 +145,7 @@ module ActiveScaffold
143
145
  config = record.is_a?(active_scaffold_config.model) ? active_scaffold_config : active_scaffold_config_for(record.class)
144
146
  constraints.each do |k, v|
145
147
  column = config.columns[k]
146
- if column && column.association
148
+ if column&.association
147
149
  if column.association.collection?
148
150
  record.send(k.to_s).send(:<<, column.association.klass.find(v))
149
151
  elsif column.association.polymorphic?
@@ -151,7 +153,7 @@ module ActiveScaffold
151
153
  raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(column.association), caller
152
154
  end
153
155
  record.send("#{k}=", v[0].constantize.find(v[1]))
154
- else # regular singular association
156
+ elsif !column.association.source_reflection&.options&.include?(:through) # regular singular association, or one-level through association
155
157
  record.send("#{k}=", column.association.klass.find(v))
156
158
 
157
159
  # setting the belongs_to side of a has_one isn't safe. if the has_one was already
@@ -4,12 +4,44 @@ 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
+ return if 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
+
7
17
  def active_scaffold_config
8
- self.class.active_scaffold_config
18
+ @active_scaffold_config ||= begin
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
+ end
27
+
28
+ def active_scaffold_session_storage_key(id = nil)
29
+ id ||= params[:eid] || "#{params[:controller]}#{"_#{nested_parent_id}" if nested?}"
30
+ "as:#{id}"
9
31
  end
10
32
 
11
- def active_scaffold_config_for(klass)
12
- self.class.active_scaffold_config_for(klass)
33
+ def active_scaffold_session_storage(id = nil)
34
+ session_index = active_scaffold_session_storage_key(id)
35
+ session[session_index] ||= {}
36
+ session[session_index]
37
+ end
38
+
39
+ def user_settings_storage
40
+ if self.class.active_scaffold_config.store_user_settings
41
+ active_scaffold_session_storage
42
+ else
43
+ {}
44
+ end
13
45
  end
14
46
 
15
47
  module ClassMethods
@@ -29,8 +61,13 @@ module ActiveScaffold
29
61
  active_scaffold_superclasses_blocks.each { |superblock| active_scaffold_config.configure(&superblock) }
30
62
  active_scaffold_config.sti_children = nil # reset sti_children if set in parent block
31
63
  active_scaffold_config.configure(&block) if block_given?
32
- active_scaffold_config._configure_sti unless active_scaffold_config.sti_children.nil?
33
- active_scaffold_config._load_action_columns
64
+ active_scaffold_config.class.after_config_callbacks.each do |callback|
65
+ if callback.is_a?(Proc)
66
+ callback.call
67
+ elsif active_scaffold_config.respond_to?(callback)
68
+ active_scaffold_config.send(callback)
69
+ end
70
+ end
34
71
 
35
72
  # defines the attribute read methods on the model, so record.send() doesn't find protected/private methods instead
36
73
  # define_attribute_methods is safe to call multiple times since rails 4.0.4
@@ -46,6 +83,7 @@ module ActiveScaffold
46
83
  active_scaffold_config.actions.each do |mod|
47
84
  include "ActiveScaffold::Actions::#{mod.to_s.camelize}".constantize
48
85
  mod_conf = active_scaffold_config.send(mod)
86
+ active_scaffold_config._setup_action(mod) if ActiveScaffold.threadsafe
49
87
  next unless mod_conf.respond_to?(:link) && (link = mod_conf.link)
50
88
 
51
89
  # sneak the action links from the actions into the main set
@@ -59,10 +97,13 @@ module ActiveScaffold
59
97
  end
60
98
  end
61
99
  _add_sti_create_links if active_scaffold_config.add_sti_create_links?
100
+ return unless ActiveScaffold.threadsafe
101
+ active_scaffold_config._cache_lazy_values
102
+ active_scaffold_config.deep_freeze!
62
103
  end
63
104
 
64
105
  module Prefixes
65
- define_method Rails.version < '4.2' ? 'parent_prefixes' : 'local_prefixes' do
106
+ define_method 'local_prefixes' do
66
107
  @local_prefixes ||= begin
67
108
  prefixes = super()
68
109
  unless superclass.uses_active_scaffold? || prefixes.include?('active_scaffold_overrides')
@@ -87,7 +128,8 @@ module ActiveScaffold
87
128
  end
88
129
  end
89
130
 
90
- # Create the automatic column links. Note that this has to happen when configuration is *done*, because otherwise the Nested module could be disabled. Actually, it could still be disabled later, couldn't it?
131
+ # Create the automatic column links. Note that this has to happen when configuration is *done*,
132
+ # because otherwise the Nested module could be disabled. Actually, it could still be disabled later, couldn't it?
91
133
  def links_for_associations
92
134
  return unless active_scaffold_config.actions.include?(:list) && active_scaffold_config.actions.include?(:nested)
93
135
  active_scaffold_config.columns.each do |column|
@@ -122,10 +164,13 @@ module ActiveScaffold
122
164
  else
123
165
  actions = controller.active_scaffold_config.actions unless controller == :polymorph
124
166
  actions ||= %i[create update show]
125
- column.actions_for_association_links.delete :new unless actions.include? :create
126
- column.actions_for_association_links.delete :edit unless actions.include? :update
127
- column.actions_for_association_links.delete :show unless actions.include? :show
128
- ActiveScaffold::DataStructures::ActionLink.new(nil, options.merge(:html_options => {:class => column.name}))
167
+ controller_actions = column.actions_for_association_links
168
+ controller_actions = controller_actions.dup if controller_actions.frozen?
169
+ controller_actions.delete :new unless actions.include? :create
170
+ controller_actions.delete :edit unless actions.include? :update
171
+ controller_actions.delete :show unless actions.include? :show
172
+ options.merge!(html_options: {class: column.name}, controller_actions: Set.new(controller_actions))
173
+ ActiveScaffold::DataStructures::ActionLink.new(nil, options)
129
174
  end
130
175
  end
131
176
 
@@ -167,17 +212,14 @@ module ActiveScaffold
167
212
  end
168
213
 
169
214
  def active_scaffold_config_for(klass)
170
- controller = active_scaffold_controller_for(klass)
215
+ active_scaffold_controller_for(klass).active_scaffold_config
171
216
  rescue ActiveScaffold::ControllerNotFound
172
- config = ActiveScaffold::Config::Core.new(klass)
173
- config._load_action_columns
174
- config
175
- else
176
- controller.active_scaffold_config
217
+ ActiveScaffold::Config::Core.new(klass)
177
218
  end
178
219
 
179
220
  def active_scaffold_controller_for(klass)
180
221
  return self if uses_active_scaffold? && klass == active_scaffold_config.model
222
+ # noinspection RubyArgCount
181
223
  ActiveScaffold::Core.active_scaffold_controller_for(klass, to_s.deconstantize + '::')
182
224
  end
183
225
 
@@ -198,12 +240,9 @@ module ActiveScaffold
198
240
  controller = "#{namespace}#{controller_name.camelize}Controller".constantize
199
241
  rescue NameError => error
200
242
  # Only rescue NameError associated with the controller constant not existing - not other compile errors
201
- if error.message["uninitialized constant #{controller}"]
202
- error_message << "#{namespace}#{controller_name.camelize}Controller"
203
- next
204
- else
205
- raise
206
- end
243
+ raise unless error.message["uninitialized constant #{controller}"]
244
+ error_message << "#{namespace}#{controller_name.camelize}Controller"
245
+ next
207
246
  end
208
247
  raise ActiveScaffold::ControllerNotFound, "#{controller} missing ActiveScaffold", caller unless controller.uses_active_scaffold?
209
248
  unless controller.active_scaffold_config.model.to_s == klass.to_s
@@ -216,9 +255,9 @@ module ActiveScaffold
216
255
  end
217
256
 
218
257
  def self.column_type_cast(value, column)
219
- if defined?(ActiveRecord) && ActiveRecord::ConnectionAdapters::Column === column
258
+ if defined?(ActiveRecord) && column.is_a?(ActiveRecord::ConnectionAdapters::Column)
220
259
  active_record_column_type_cast(value, column)
221
- elsif defined?(Mongoid) && Mongoid::Fields::Standard === column
260
+ elsif defined?(Mongoid) && column.is_a?(Mongoid::Fields::Standard)
222
261
  mongoid_column_type_cast(value, column)
223
262
  else
224
263
  value
@@ -226,13 +265,13 @@ module ActiveScaffold
226
265
  end
227
266
 
228
267
  def self.mongoid_column_type_cast(value, column)
268
+ return Time.zone.at(value.to_i) if value =~ /\A\d+\z/ && [Time, DateTime].include?(column.type)
229
269
  column.type.evolve value
230
270
  end
231
271
 
232
272
  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'
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'
236
275
  column.type_cast_from_user value
237
276
  elsif column.type.respond_to? :cast # jruby-jdbc and rails 5
238
277
  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 = options[:core_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