active_scaffold 3.5.3 → 3.6.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +73 -0
  3. data/README.md +17 -7
  4. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  5. data/app/assets/javascripts/jquery/active_scaffold.js +97 -6
  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 +1 -0
  63. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  64. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  65. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -12
  66. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  67. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  68. data/lib/active_scaffold/bridges/chosen/helpers.rb +11 -9
  69. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  70. data/lib/active_scaffold/bridges/date_picker/helper.rb +49 -44
  71. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  72. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  73. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  74. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  75. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +10 -7
  76. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  77. data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
  78. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  79. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  80. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  81. data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -17
  82. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -19
  83. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  84. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +21 -4
  85. data/lib/active_scaffold/config/base.rb +133 -41
  86. data/lib/active_scaffold/config/core.rb +146 -18
  87. data/lib/active_scaffold/config/delete.rb +14 -1
  88. data/lib/active_scaffold/config/field_search.rb +7 -1
  89. data/lib/active_scaffold/config/form.rb +10 -1
  90. data/lib/active_scaffold/config/list.rb +39 -13
  91. data/lib/active_scaffold/config/mark.rb +4 -2
  92. data/lib/active_scaffold/config/nested.rb +16 -17
  93. data/lib/active_scaffold/config/search.rb +9 -0
  94. data/lib/active_scaffold/config/show.rb +4 -0
  95. data/lib/active_scaffold/config/update.rb +4 -0
  96. data/lib/active_scaffold/configurable.rb +14 -7
  97. data/lib/active_scaffold/constraints.rb +22 -20
  98. data/lib/active_scaffold/core.rb +67 -28
  99. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  100. data/lib/active_scaffold/data_structures/action_link.rb +50 -20
  101. data/lib/active_scaffold/data_structures/action_links.rb +15 -13
  102. data/lib/active_scaffold/data_structures/association/abstract.rb +38 -15
  103. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  104. data/lib/active_scaffold/data_structures/association/active_record.rb +6 -2
  105. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  106. data/lib/active_scaffold/data_structures/column.rb +75 -66
  107. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  108. data/lib/active_scaffold/data_structures/nested_info.rb +33 -19
  109. data/lib/active_scaffold/data_structures/set.rb +8 -0
  110. data/lib/active_scaffold/data_structures/sorting.rb +10 -2
  111. data/lib/active_scaffold/delayed_setup.rb +16 -5
  112. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -2
  113. data/lib/active_scaffold/extensions/action_view_rendering.rb +34 -14
  114. data/lib/active_scaffold/extensions/cow_proxy.rb +95 -0
  115. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  116. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  117. data/lib/active_scaffold/extensions/localize.rb +3 -1
  118. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -45
  119. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  120. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  121. data/lib/active_scaffold/finder.rb +110 -77
  122. data/lib/active_scaffold/helpers/action_link_helpers.rb +62 -36
  123. data/lib/active_scaffold/helpers/association_helpers.rb +21 -19
  124. data/lib/active_scaffold/helpers/controller_helpers.rb +34 -10
  125. data/lib/active_scaffold/helpers/form_column_helpers.rb +196 -124
  126. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  127. data/lib/active_scaffold/helpers/id_helpers.rb +6 -2
  128. data/lib/active_scaffold/helpers/list_column_helpers.rb +86 -57
  129. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  130. data/lib/active_scaffold/helpers/search_column_helpers.rb +29 -34
  131. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  132. data/lib/active_scaffold/helpers/view_helpers.rb +38 -35
  133. data/lib/active_scaffold/marked_model.rb +2 -2
  134. data/lib/active_scaffold/orm_checks.rb +3 -7
  135. data/lib/active_scaffold/paginator.rb +7 -7
  136. data/lib/active_scaffold/registry.rb +33 -0
  137. data/lib/active_scaffold/responds_to_parent.rb +8 -11
  138. data/lib/active_scaffold/tableless.rb +67 -65
  139. data/lib/active_scaffold/version.rb +2 -2
  140. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  141. data/lib/generators/active_scaffold/install_generator.rb +1 -1
  142. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  143. data/shoulda_macros/macros.rb +3 -1
  144. data/test/bridges/date_picker_test.rb +1 -2
  145. data/test/bridges/paperclip_test.rb +6 -6
  146. data/test/class_with_finder.rb +2 -2
  147. data/test/company.rb +4 -4
  148. data/test/config/create_test.rb +4 -2
  149. data/test/config/nested_test.rb +1 -1
  150. data/test/config/show_test.rb +1 -1
  151. data/test/config/update_test.rb +7 -6
  152. data/test/data_structures/action_columns_test.rb +2 -2
  153. data/test/data_structures/action_links_test.rb +1 -1
  154. data/test/data_structures/column_test.rb +3 -6
  155. data/test/data_structures/columns_test.rb +2 -2
  156. data/test/data_structures/sorting_test.rb +7 -0
  157. data/test/extensions/active_record_test.rb +4 -4
  158. data/test/extensions/routing_mapper_test.rb +2 -2
  159. data/test/helpers/list_column_helpers_test.rb +3 -1
  160. data/test/misc/active_record_permissions_test.rb +3 -11
  161. data/test/misc/attribute_params_test.rb +12 -8
  162. data/test/misc/calculation_test.rb +1 -1
  163. data/test/misc/configurable_test.rb +10 -10
  164. data/test/misc/constraints_test.rb +2 -2
  165. data/test/misc/convert_numbers_format_test.rb +7 -3
  166. data/test/misc/lang_test.rb +1 -1
  167. data/test/misc/parse_datetime_test.rb +3 -4
  168. data/test/misc/tableless_test.rb +6 -0
  169. data/test/mock_app/Rakefile +1 -1
  170. data/test/mock_app/app/assets/config/manifest.js +0 -0
  171. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  172. data/test/mock_app/app/controllers/people_controller.rb +3 -1
  173. data/test/mock_app/config/application.rb +2 -1
  174. data/test/mock_app/config/boot.rb +1 -1
  175. data/test/mock_app/config/environment.rb +2 -2
  176. data/test/mock_app/config/routes.rb +4 -1
  177. data/test/mock_app/db/schema.rb +2 -0
  178. data/test/performance/list_cars_performance_test.rb +34 -0
  179. data/test/performance/list_people_performance_test.rb +31 -0
  180. data/test/performance_test_help.rb +3 -0
  181. data/test/test_helper.rb +10 -2
  182. metadata +55 -20
  183. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  184. 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